diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index ac428f246e..2c7017cf70 100644
--- a/src/SUMMARY.md
+++ b/src/SUMMARY.md
@@ -295,7 +295,9 @@
- [AWS - EFS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md)
- [AWS - EKS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md)
- [AWS - Elastic Beanstalk Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md)
+ - [AWS - Glue Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-glue-post-exploitation/README.md)
- [AWS - IAM Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md)
+ - [AWS resource-policy principal validation](pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/aws-resource-policy-principal-validation.md)
- [AWS - KMS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-kms-post-exploitation/README.md)
- [AWS - Lambda Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md)
- [AWS - Lambda EFS Mount Injection](pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-efs-mount-injection.md)
@@ -394,23 +396,33 @@
- [AWS - Trusted Advisor Enum](pentesting-cloud/aws-security/aws-services/aws-security-and-detection-services/aws-trusted-advisor-enum.md)
- [AWS - WAF Enum](pentesting-cloud/aws-security/aws-services/aws-security-and-detection-services/aws-waf-enum.md)
- [AWS - Account Management Enum](pentesting-cloud/aws-security/aws-services/aws-account-management-enum.md)
+ - [AWS - Amazon Connect Enum](pentesting-cloud/aws-security/aws-services/aws-connect-enum.md)
+ - [AWS - Amazon Connect Customer Profiles Enum](pentesting-cloud/aws-security/aws-services/aws-connect-customer-profiles-enum.md)
+ - [AWS - Amazon Q in Connect Enum](pentesting-cloud/aws-security/aws-services/aws-q-in-connect-enum.md)
- [AWS - API Gateway Enum](pentesting-cloud/aws-security/aws-services/aws-api-gateway-enum.md)
+ - [AWS - AppConfig Enum](pentesting-cloud/aws-security/aws-services/aws-appconfig-enum.md)
+ - [AWS - AppSync Enum](pentesting-cloud/aws-security/aws-services/aws-appsync-enum.md)
+ - [AWS - Aurora DSQL Enum](pentesting-cloud/aws-security/aws-services/aws-aurora-dsql-enum.md)
+ - [AWS - Batch Enum](pentesting-cloud/aws-security/aws-services/aws-batch-enum.md)
- [AWS - Bedrock Enum](pentesting-cloud/aws-security/aws-services/aws-bedrock-enum.md)
- [AWS - Certificate Manager (ACM) & Private Certificate Authority (PCA)](pentesting-cloud/aws-security/aws-services/aws-certificate-manager-acm-and-private-certificate-authority-pca.md)
- [AWS - CloudFormation & Codestar Enum](pentesting-cloud/aws-security/aws-services/aws-cloudformation-and-codestar-enum.md)
- [AWS - CloudHSM Enum](pentesting-cloud/aws-security/aws-services/aws-cloudhsm-enum.md)
- [AWS - CloudFront Enum](pentesting-cloud/aws-security/aws-services/aws-cloudfront-enum.md)
- [AWS - Codebuild Enum](pentesting-cloud/aws-security/aws-services/aws-codebuild-enum.md)
+ - [AWS - CodeArtifact Enum](pentesting-cloud/aws-security/aws-services/aws-codeartifact-enum.md)
- [AWS - Cognito Enum](pentesting-cloud/aws-security/aws-services/aws-cognito-enum/README.md)
- [Cognito Identity Pools](pentesting-cloud/aws-security/aws-services/aws-cognito-enum/cognito-identity-pools.md)
- [Cognito User Pools](pentesting-cloud/aws-security/aws-services/aws-cognito-enum/cognito-user-pools.md)
- [AWS - DataPipeline, CodePipeline & CodeCommit Enum](pentesting-cloud/aws-security/aws-services/aws-datapipeline-codepipeline-codebuild-and-codecommit.md)
+ - [AWS - Deadline Cloud Enum](pentesting-cloud/aws-security/aws-services/aws-deadline-cloud-enum.md)
- [AWS - Directory Services / WorkDocs Enum](pentesting-cloud/aws-security/aws-services/aws-directory-services-workdocs-enum.md)
- [AWS - DocumentDB Enum](pentesting-cloud/aws-security/aws-services/aws-documentdb-enum/README.md)
- [AWS - DynamoDB Enum](pentesting-cloud/aws-security/aws-services/aws-dynamodb-enum.md)
- [AWS - EC2, EBS, ELB, SSM, VPC & VPN Enum](pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md)
- [AWS - Nitro Enum](pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/aws-nitro-enum.md)
- [AWS - VPC & Networking Basic Information](pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/aws-vpc-and-networking-basic-information.md)
+ - [AWS - EC2 Image Builder Enum](pentesting-cloud/aws-security/aws-services/aws-ec2-image-builder-enum.md)
- [AWS - ECR Enum](pentesting-cloud/aws-security/aws-services/aws-ecr-enum.md)
- [AWS - ECS Enum](pentesting-cloud/aws-security/aws-services/aws-ecs-enum.md)
- [AWS - EKS Enum](pentesting-cloud/aws-security/aws-services/aws-eks-enum.md)
@@ -420,12 +432,20 @@
- [AWS - EFS Enum](pentesting-cloud/aws-security/aws-services/aws-efs-enum.md)
- [AWS - EventBridge Scheduler Enum](pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md)
- [AWS - Kinesis Data Firehose Enum](pentesting-cloud/aws-security/aws-services/aws-kinesis-data-firehose-enum.md)
+ - [AWS - Kinesis Data Streams Enum](pentesting-cloud/aws-security/aws-services/aws-kinesis-data-streams-enum.md)
+ - [AWS - Managed Service for Apache Flink Enum](pentesting-cloud/aws-security/aws-services/aws-managed-flink-enum.md)
+ - [AWS - Managed Service for Prometheus Enum](pentesting-cloud/aws-security/aws-services/aws-managed-prometheus-enum.md)
- [AWS - IAM, Identity Center & SSO Enum](pentesting-cloud/aws-security/aws-services/aws-iam-enum.md)
- [AWS - Invoicing Enum](pentesting-cloud/aws-security/aws-services/aws-invoicing-enum.md)
+ - [AWS - IoT Core Enum](pentesting-cloud/aws-security/aws-services/aws-iot-core-enum.md)
+ - [AWS - IoT Wireless Enum](pentesting-cloud/aws-security/aws-services/aws-iot-wireless-enum.md)
+ - [AWS - IoT Greengrass Enum](pentesting-cloud/aws-security/aws-services/aws-greengrass-enum.md)
- [AWS - KMS Enum](pentesting-cloud/aws-security/aws-services/aws-kms-enum.md)
- [AWS - Lambda Enum](pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md)
+ - [AWS - Lex V2 Enum](pentesting-cloud/aws-security/aws-services/aws-lex-v2-enum.md)
- [AWS - Lightsail Enum](pentesting-cloud/aws-security/aws-services/aws-lightsail-enum.md)
- [AWS - Macie Enum](pentesting-cloud/aws-security/aws-services/aws-macie-enum.md)
+ - [AWS - MediaPackage v2 Enum](pentesting-cloud/aws-security/aws-services/aws-mediapackage-v2-enum.md)
- [AWS - MQ Enum](pentesting-cloud/aws-security/aws-services/aws-mq-enum.md)
- [AWS - MSK Enum](pentesting-cloud/aws-security/aws-services/aws-msk-enum.md)
- [AWS - Organizations Enum](pentesting-cloud/aws-security/aws-services/aws-organizations-enum.md)
@@ -438,9 +458,12 @@
- [AWS - SNS Enum](pentesting-cloud/aws-security/aws-services/aws-sns-enum.md)
- [AWS - SQS Enum](pentesting-cloud/aws-security/aws-services/aws-sqs-and-sns-enum.md)
- [AWS - S3, Athena & Glacier Enum](pentesting-cloud/aws-security/aws-services/aws-s3-athena-and-glacier-enum.md)
+ - [AWS - S3 Tables and S3 Vectors Enum](pentesting-cloud/aws-security/aws-services/aws-s3-tables-and-vectors-enum.md)
- [AWS - Step Functions Enum](pentesting-cloud/aws-security/aws-services/aws-stepfunctions-enum.md)
- [AWS - STS Enum](pentesting-cloud/aws-security/aws-services/aws-sts-enum.md)
- [AWS - Tax Settings Enum](pentesting-cloud/aws-security/aws-services/aws-tax-settings-enum.md)
+ - [AWS - Transcribe Enum](pentesting-cloud/aws-security/aws-services/aws-transcribe-enum.md)
+ - [AWS - VPC Lattice Enum](pentesting-cloud/aws-security/aws-services/aws-vpc-lattice-enum.md)
- [AWS - WorkMail Enum](pentesting-cloud/aws-security/aws-services/aws-workmail-enum.md)
- [AWS - WorkSpaces Enum](pentesting-cloud/aws-security/aws-services/aws-workspaces-enum.md)
- [AWS - Other Services Enum](pentesting-cloud/aws-security/aws-services/aws-other-services-enum.md)
diff --git a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-glue-post-exploitation/README.md b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-glue-post-exploitation/README.md
new file mode 100644
index 0000000000..a051054bde
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-glue-post-exploitation/README.md
@@ -0,0 +1,86 @@
+# AWS - Glue Post Exploitation
+
+{{#include ../../../../banners/hacktricks-training.md}}
+
+AWS Glue stores job definitions, connection profiles, crawlers, workflows, and Data Catalog metadata in its control plane. Some read APIs return operator-supplied values verbatim, so read-only Glue access can disclose credentials before any job is executed.
+
+## glue:GetConnection — tested plaintext connection credentials
+
+A Glue connection can hold JDBC URLs, usernames, passwords, tokens, and service-specific properties in ConnectionProperties. GetConnection accepts a caller-controlled HidePassword flag; request false when testing whether the password is recoverable.[[1]](#references)[[2]](#references)
+
+~~~bash
+aws glue get-connection \
+ --name \
+ --no-hide-password \
+ --region \
+ --query 'Connection.{Name:Name,Type:ConnectionType,Properties:ConnectionProperties}'
+~~~
+
+{% hint style="danger" %}
+This was validated with an STS session policy containing only **glue:GetConnection**. A disposable JDBC connection held a unique random value in its PASSWORD property; the response returned that value exactly. No network connection or Glue job was run. The connection and test role were then deleted. Treat the action as **high** because it can directly return reusable data-store credentials.
+{% endhint %}
+
+The result depends on how the connection was configured. Secrets referenced indirectly through Secrets Manager are identifiers rather than secret values and require separate Secrets Manager access. When Glue Data Catalog encryption uses a customer KMS key, effective access can also depend on the key policy and **kms:Decrypt**; do not assume every connection password is decryptable merely because GetConnection is allowed.[[2]](#references)[[3]](#references)
+
+## glue:GetJob — tested job-argument and environment disclosure
+
+GetJob returns the job definition, including its execution role, command and script location, Glue connections, default arguments, non-overridable arguments, worker configuration, security configuration, and execution-class settings.[[4]](#references) Developers sometimes put database passwords, API tokens, internal URLs, or feature credentials directly in argument maps.
+
+~~~bash
+aws glue get-job --job-name --region \
+ --query 'Job.{Role:Role,Command:Command,Connections:Connections,DefaultArguments:DefaultArguments,NonOverridableArguments:NonOverridableArguments,SecurityConfiguration:SecurityConfiguration}'
+~~~
+
+{% hint style="danger" %}
+This was validated independently with an STS session policy containing only **glue:GetJob**. A disposable, never-executed ETL job stored a random sentinel in DefaultArguments; GetJob returned the exact plaintext value. The job, its unused service role, and the reader role were deleted. Treat the action as **high** for secret discovery, but not as privilege escalation by itself.
+{% endhint %}
+
+Reading a role ARN or script location does not grant that role or S3 object. Actual code access needs the relevant S3 permission, and executing or changing the job needs the separate Glue write/run and iam:PassRole paths described in the Glue privilege-escalation page.
+
+## glue:GetWorkflowRunProperties — tested run-property disclosure
+
+Glue workflow run properties are a string-to-string map used to pass shared state between jobs, crawlers, and triggers in one workflow run. Properties can hold dataset locations, database connection information, tokens, or other operator-supplied values. `GetWorkflowRunProperties` returns the complete map for a known workflow name and run ID.[[5]](#references)[[6]](#references)
+
+~~~bash
+# The workflow name and run ID can be supplied directly.
+aws glue get-workflow-run-properties \
+ --name \
+ --run-id \
+ --query RunProperties
+~~~
+
+{% hint style="danger" %}
+This was validated with an STS session restricted to `glue:GetWorkflowRunProperties`. A disposable workflow run stored a unique random sentinel through `PutWorkflowRunProperties`; the exact read returned it. The run was stopped immediately, and its trigger, tiny Python-shell job, workflow, script bucket, service role, and reader role were deleted. Treat the read as **high** for literal shared run state. It does not allow modification, job execution, or access to an S3/Secrets Manager value that is only referenced.
+{% endhint %}
+
+If Glue list/read APIs are unavailable, workflow names and run IDs may still appear in CloudFormation/Terraform, CloudTrail, Step Functions or EventBridge configuration, CI/CD logs, Glue job arguments, CloudWatch logs, console URLs, source code, or local shell history. Run properties are per-run, so enumerate only run IDs learned through an authorized source and do not assume the newest run contains the same values as older runs.
+
+{{#ref}}
+../../aws-privilege-escalation/aws-glue-privesc/README.md
+{{#endref}}
+
+## Discovery without Glue list permissions
+
+GetConnection, GetJob, and GetWorkflowRunProperties accept specific identifiers, so Glue list permissions are not required when they are already known. Search these permissionless or independently authorized sources:
+
+* application source, IaC, deployment manifests, CI/CD output, shell history, tickets, and notebooks;
+* CloudTrail events such as CreateJob, UpdateJob, StartJobRun, CreateConnection, and UpdateConnection;
+* Step Functions definitions, EventBridge targets, Lambda environment variables, and Glue workflow/crawler references; and
+* predictable environment prefixes such as dev-, staging-, and prod-.
+
+If both Glue reads are denied, independently readable job scripts, CloudWatch logs, Secrets Manager entries, SSM parameters, and target data stores remain separate fallbacks. Each requires its own authorization; their mere names are not proof of data access.
+
+## Tested cleanup
+
+The connection/job-definition validation created no compute and started no job. The workflow-property validation briefly started a disposable workflow and immediately stopped its minimum-capacity Python-shell job. DeleteConnection, DeleteJob, DeleteTrigger, DeleteWorkflow, S3 bucket deletion, and IAM role deletion completed; follow-up Glue, S3, IAM, log-stream, tag, and service-specific lists found no live lab resources.
+
+## References
+
+- [1] [GetConnection API](https://docs.aws.amazon.com/glue/latest/webapi/API_GetConnection.html)
+- [2] [Connection structure and properties](https://docs.aws.amazon.com/glue/latest/webapi/API_Connection.html)
+- [3] [Encrypting the Data Catalog](https://docs.aws.amazon.com/glue/latest/dg/encrypt-glue-data-catalog.html)
+- [4] [GetJob API](https://docs.aws.amazon.com/glue/latest/webapi/API_GetJob.html)
+- [5] [Sharing properties between jobs in an AWS Glue workflow](https://docs.aws.amazon.com/glue/latest/dg/workflow-run-properties-code.html)
+- [6] [GetWorkflowRunProperties API](https://docs.aws.amazon.com/glue/latest/webapi/API_GetWorkflowRunProperties.html)
+
+{{#include ../../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md
index 2c796cb54c..da8a01d176 100644
--- a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md
+++ b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md
@@ -10,6 +10,14 @@ For more information about IAM access:
../../aws-services/aws-iam-enum.md
{{#endref}}
+### Resource-policy principal validation
+
+When a compromised principal can update resource-based policies, several AWS services can validate candidate external account IDs or IAM principal names. This is an expected post-exploitation reconnaissance technique—not cross-account access or a vulnerability—and every tested operation changes policy state.
+
+{{#ref}}
+aws-resource-policy-principal-validation.md
+{{#endref}}
+
## Confused Deputy Problem
If you **allow an external account (A)** to access a **role** in your account, you will probably have **0 visibility** on **who can exactly access that external account**. This is a problem, because if another external account (B) can access the external account (A) it's possible that **B will also be able to access your account**.[[1]](#references)
diff --git a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/aws-resource-policy-principal-validation.md b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/aws-resource-policy-principal-validation.md
new file mode 100644
index 0000000000..b925a462ac
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/aws-resource-policy-principal-validation.md
@@ -0,0 +1,205 @@
+# AWS resource-policy principal validation
+
+{{#include ../../../../banners/hacktricks-training.md}}
+
+## What this technique is
+
+Several AWS services validate the `Principal` in a resource-based policy when an authorized caller writes that policy. On the tested APIs, a policy naming an existing external IAM user is accepted, while the same policy naming a nonexistent user is rejected. Some APIs also distinguish allocated from unallocated AWS account IDs.
+
+{% hint style="warning" %}
+This is **expected resource-policy validation behavior**, not an AWS vulnerability and not cross-account compromise. It only confirms an identifier. It does not grant credentials, assume a role, read victim data, or change the external account.
+{% endhint %}
+
+The technique can still be useful after compromising an AWS principal: confirmed account IDs, IAM usernames, or role names can focus searches for leaked credentials, public trust policies, deployment artifacts, and later authorized cross-account testing.
+
+## Preconditions and safety
+
+Every operation below is a **write or permissions-management action** on a resource in the compromised account. A read-only enumerator such as `awspeass` must never execute these calls automatically; it should only report that the caller appears to have the relevant permission and explain the optional manual technique.
+
+Before testing an existing resource:
+
+1. Retrieve and save its current policy with the corresponding `Get*Policy` operation.
+2. Use a disposable resource whenever possible. A `Put*Policy` call usually replaces the complete policy.
+3. Test only accounts and identities you are authorized to assess.
+4. Restore the exact original policy afterward, or delete the test policy only when no policy existed before.
+5. Treat throttling, conflicts, malformed-policy errors, and transient service errors as **inconclusive** unless they match the controlled result for that API.
+
+The candidate policy has this general shape:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [{
+ "Sid": "PrincipalValidation",
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::TARGET_ACCOUNT:user/CANDIDATE_NAME"
+ },
+ "Action": "VALID_RESOURCE_ACTION",
+ "Resource": "OWNED_RESOURCE_ARN"
+ }]
+}
+```
+
+Use a harmless read action supported by the resource policy. Change only the candidate principal between the positive and negative controls.
+
+## Tested service matrix
+
+The following behaviors were reproduced in `us-east-1` on 2026-09-08 with disposable, empty resources. Each existing external user and its random nonexistent-user control belonged to an account controlled by the tester.
+
+| Service and owned resource | Required policy-write action | Policy action used | Existing external user | Nonexistent external user |
+|---|---|---|---|---|
+| Bedrock AgentCore Memory | `bedrock-agentcore:PutResourcePolicy` | `bedrock-agentcore:*` | Success | `ValidationException: Invalid principal in policy` |
+| Amazon Managed Service for Prometheus workspace | `aps:PutResourcePolicy` | `aps:QueryMetrics` | Success | `ValidationException: Resource policy cannot contain non-existing Principals` |
+| CloudWatch Logs delivery destination | `logs:PutDeliveryDestinationPolicy` | `logs:CreateDelivery` | Success | Generic invalid-policy `ValidationException` |
+| CodeArtifact domain | `codeartifact:PutDomainPermissionsPolicy` | `codeartifact:GetAuthorizationToken` | Success | Generic invalid-policy `ValidationException` |
+| Aurora DSQL cluster | `dsql:PutClusterPolicy` | `dsql:DbConnect` | Success | Generic invalid-policy `ValidationException` |
+| DynamoDB table | `dynamodb:PutResourcePolicy` | `dynamodb:GetItem` | Success | `ValidationException: Invalid principal in policy document` |
+| Kinesis data stream | `kinesis:PutResourcePolicy` | `kinesis:DescribeStreamSummary` | Success | `InvalidArgumentException: Invalid principal in policy document` |
+| MediaPackage v2 channel | `mediapackagev2:PutChannelPolicy` | `mediapackagev2:PutObject` | Success | Generic invalid-policy `ValidationException` |
+| CloudWatch OAM sink | `oam:PutSinkPolicy` | `oam:CreateLink` | Success | `InvalidParameterException: Policy validation failed` |
+| S3 Tables table bucket | `s3tables:PutTableBucketPolicy` | `s3tables:GetTableBucket` | Success | `BadRequestException: Invalid principal in policy` |
+| S3 Tables table | `s3tables:PutTablePolicy` | `s3tables:GetTableMetadataLocation` | Success | `BadRequestException: Invalid principal in policy` |
+| S3 Vectors vector bucket | `s3vectors:PutVectorBucketPolicy` | `s3vectors:GetVectorBucket` | Success | `ValidationException: Invalid principal in policy` |
+| VPC Lattice service network | `vpc-lattice:PutAuthPolicy` | `vpc-lattice-svcs:Invoke` | Success | `ValidationException: Policy principal is not found` |
+
+Route 53 Resolver DNS Firewall behaved differently: `route53resolver:PutFirewallRuleGroupPolicy` on an empty, owned firewall rule group accepted allocated account IDs and returned `InternalServiceErrorException` with resolver code `RSLVR-00200` for unallocated IDs. This validates account allocation only; it does not enumerate an IAM username.
+
+## CLI operations
+
+Save the service-specific JSON as `candidate-policy.json`, then use the matching command:
+
+```bash
+# Bedrock AgentCore
+aws bedrock-agentcore-control put-resource-policy \
+ --resource-arn \
+ --policy file://candidate-policy.json
+
+# Amazon Managed Service for Prometheus
+aws amp put-resource-policy \
+ --workspace-id \
+ --policy-document file://candidate-policy.json
+
+# CloudWatch Logs delivery destination
+aws logs put-delivery-destination-policy \
+ --delivery-destination-name \
+ --delivery-destination-policy file://candidate-policy.json
+
+# CodeArtifact
+aws codeartifact put-domain-permissions-policy \
+ --domain \
+ --policy-document file://candidate-policy.json
+
+# Aurora DSQL
+aws dsql put-cluster-policy \
+ --identifier \
+ --policy file://candidate-policy.json \
+ --bypass-policy-lockout-safety-check
+
+# DynamoDB
+aws dynamodb put-resource-policy \
+ --resource-arn \
+ --policy file://candidate-policy.json
+
+# Kinesis Data Streams
+aws kinesis put-resource-policy \
+ --resource-arn \
+ --policy file://candidate-policy.json
+
+# MediaPackage v2
+aws mediapackagev2 put-channel-policy \
+ --channel-group-name \
+ --channel-name \
+ --policy file://candidate-policy.json
+
+# CloudWatch Observability Access Manager
+aws oam put-sink-policy \
+ --sink-identifier \
+ --policy file://candidate-policy.json
+
+# S3 Tables table bucket
+aws s3tables put-table-bucket-policy \
+ --table-bucket-arn \
+ --resource-policy file://candidate-policy.json
+
+# S3 Tables individual table
+aws s3tables put-table-policy \
+ --table-bucket-arn \
+ --namespace \
+ --name \
+ --resource-policy file://candidate-policy.json
+
+# S3 Vectors
+aws s3vectors put-vector-bucket-policy \
+ --vector-bucket-name \
+ --policy file://candidate-policy.json
+
+# VPC Lattice
+aws vpc-lattice put-auth-policy \
+ --resource-identifier \
+ --policy file://candidate-policy.json
+```
+
+For the Route 53 Resolver account-ID check, the tested policy used a bare 12-digit account ID and the exact read actions in AWS RAM's default permission for DNS Firewall rule groups:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [{
+ "Effect": "Allow",
+ "Principal": {"AWS": "TARGET_12_DIGIT_ACCOUNT_ID"},
+ "Action": [
+ "route53resolver:GetFirewallRuleGroup",
+ "route53resolver:ListFirewallRuleGroups"
+ ],
+ "Resource": "FIREWALL_RULE_GROUP_ARN"
+ }]
+}
+```
+
+```bash
+aws route53resolver put-firewall-rule-group-policy \
+ --arn \
+ --firewall-rule-group-policy file://candidate-policy.json
+```
+
+## When list permissions are denied
+
+The policy-write permission is still mandatory, but list permissions are only a discovery convenience. Resource names and ARNs may already exist in:
+
+- CloudFormation/Terraform state and deployment output
+- CloudTrail copies, application logs, CI/CD logs, and shell history
+- environment variables, configuration files, source code, and console URLs
+- tags visible through another API, monitoring labels, support bundles, and error messages
+- cached AWS CLI/SDK requests or local package/build configuration
+
+If no owned resource identifier can be recovered and creation is not authorized, stop: there is no permissionless way to execute this policy-validation technique. Account IDs and principal names can still be collected passively from ARNs, public repositories, leaked policies, documentation, and organizational records.
+
+## Interpreting results
+
+- A success means only that the service accepted the policy. It does **not** prove the named principal can authenticate or access anything useful.
+- A documented invalid-principal result is a negative existence signal for that exact candidate at that time.
+- A generic invalid-policy result is meaningful only after a known-existing control succeeds with an otherwise identical policy.
+- IAM propagation can briefly preserve or reject recently created/deleted identities. Repeat later before treating a result as stable.
+- Service state, policy grammar, unsupported actions, KMS restrictions, explicit denies, and rate limiting can all produce unrelated failures.
+
+## References
+
+- [1] [AWS IAM principals](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html)
+- [2] [AWS IAM resource-based policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_identity-vs-resource.html)
+- [3] [Unit 42 research on AWS resource-policy principal enumeration](https://unit42.paloaltonetworks.com/aws-resource-based-policy-apis/)
+- [4] [Bedrock AgentCore resource-based policies](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/resource-based-policies.html)
+- [5] [Amazon Managed Service for Prometheus resource-based policies](https://docs.aws.amazon.com/prometheus/latest/userguide/security_iam_service-with-iam.html)
+- [6] [CloudWatch Logs delivery destinations](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutDeliveryDestination.html)
+- [7] [CodeArtifact domain policies](https://docs.aws.amazon.com/codeartifact/latest/ug/domain-policies.html)
+- [8] [Aurora DSQL resource-based policy operations](https://docs.aws.amazon.com/aurora-dsql/latest/userguide/rbp-api-operations.html)
+- [9] [DynamoDB `PutResourcePolicy`](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutResourcePolicy.html)
+- [10] [Kinesis Data Streams `PutResourcePolicy`](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutResourcePolicy.html)
+- [11] [MediaPackage v2 `PutChannelPolicy`](https://docs.aws.amazon.com/mediapackage/latest/APIReference/API_PutChannelPolicy.html)
+- [12] [CloudWatch OAM `PutSinkPolicy`](https://docs.aws.amazon.com/OAM/latest/APIReference/API_PutSinkPolicy.html)
+- [13] [S3 Tables table-bucket policies](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-bucket-policy.html)
+- [14] [S3 Vectors vector-bucket policies](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-vectors-bucket-policy.html)
+- [15] [VPC Lattice `PutAuthPolicy`](https://docs.aws.amazon.com/vpc-lattice/latest/APIReference/API_PutAuthPolicy.html)
+- [16] [Route 53 Resolver `PutFirewallRuleGroupPolicy`](https://docs.aws.amazon.com/Route53/latest/APIReference/API_route53resolver_PutFirewallRuleGroupPolicy.html)
+
+{{#include ../../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md
index de851ace35..f6d3361a6f 100644
--- a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md
+++ b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md
@@ -31,6 +31,14 @@ aws sqs delete-message --queue-url --receipt-handle
aws sqs change-message-visibility --queue-url --receipt-handle --visibility-timeout
```
+`sqs:ReceiveMessage` alone is sufficient to read available message bodies and attributes; deletion and visibility-changing permissions are not required for disclosure. Receiving temporarily hides a message and increments its receive count, so this is not a safe action for AWSPEASS to execute automatically.
+
+{% hint style="danger" %}
+This was validated with a disposable queue containing a random sentinel. An STS session containing exactly `sqs:ReceiveMessage` recovered the full message body while setting the per-request visibility timeout to zero. The queue and role were deleted. Treat `ReceiveMessage` by itself as **high** sensitive-data access.
+{% endhint %}
+
+If `ListQueues` or `GetQueueAttributes` is denied, queue URLs frequently appear in application configuration, Lambda event-source mappings, environment variables, source code, IaC, logs, CloudTrail copies, dead-letter settings, or error messages. A known queue URL is sufficient to attempt the exact read; distinguish an empty queue from an authorization failure and remember that delayed, invisible, or long-polled messages may not appear immediately.
+
**Potential Impact**: Steal sensitive information, Message loss, data corruption, and service disruption for applications relying on the affected messages.
### `sqs:DeleteQueue`
diff --git a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md
index 1e640466d5..bd940fbfbc 100644
--- a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md
+++ b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md
@@ -73,6 +73,24 @@ aws stepfunctions untag-resource --resource-arn --tag-keys
---
+### `states:DescribeStateMachine` — tested definition-secret disclosure
+
+The state-machine definition can contain static API arguments, headers, queue payloads, function parameters, internal resource names, and credentials that were embedded directly in Amazon States Language. `DescribeStateMachine` returns that definition together with its execution role and logging/tracing configuration.[[11]](#references)[[15]](#references)
+
+```bash
+aws stepfunctions describe-state-machine \
+ --state-machine-arn \
+ --query '{roleArn:roleArn,definition:definition,logging:loggingConfiguration,tracing:tracingConfiguration}'
+```
+
+{% hint style="danger" %}
+This was tested through an STS session policy containing only `states:DescribeStateMachine`. A disposable state machine had a unique random sentinel embedded in a `Pass` state's result; the response returned the exact sentinel. The state machine was never executed and was deleted after validation. Treat this action as **high** for definition and workflow-secret disclosure, but not as privilege escalation by itself.
+{% endhint %}
+
+The action accepts a known ARN directly, so `states:ListStateMachines` is not required. Recover ARNs from application configuration, IaC, CloudTrail, EventBridge/Scheduler targets, Lambda environment variables, CI/CD logs, or error messages. If the API is denied, locally readable workflow definitions and deployment artifacts are the permissionless fallback. Reading a task's Lambda ARN or execution-role ARN does not itself grant either resource.
+
+---
+
### `states:StartExecution` -> Input Injection Into Dangerous Sinks
`states:StartExecution` starts a state-machine execution and accepts JSON input. A `Task` state can pass that input to a Lambda or another service integration, so a workflow that sends unvalidated input to a dangerous sink (for example a Lambda that does `pickle.loads(base64.b64decode(payload_b64))`) can turn **StartExecution** into code execution and data exposure without requiring permission to update the state machine.[[10]](#references)[[13]](#references)[[16]](#references)
@@ -242,6 +260,39 @@ Because the added task stores its result and then transitions to the legitimate
- Difficult to detect without auditing Lambda code or execution traces.
- Enables long-term persistence if the backdoor remains in Lambda code or ASL logic.[[19]](#references)[[20]](#references)
+### Read execution data with `DescribeExecution` and `GetExecutionHistory`
+
+Step Functions can retain workflow input, output, state input/output, errors, and service parameters. Two read-only permissions expose different views when an execution ARN is known:[[14]](#references)[[21]](#references)
+
+```bash
+aws stepfunctions describe-execution --execution-arn
+aws stepfunctions get-execution-history --execution-arn \
+ --include-execution-data
+```
+
+`states:DescribeExecution` returns the top-level execution `input` and, once available, `output`. `states:GetExecutionHistory` returns event-by-event state data and failures. The former normally applies to Standard workflows; Express executions are not supported unless dispatched by a Map Run.[[14]](#references)
+
+{% hint style="danger" %}
+Both actions were validated independently through STS sessions containing exactly one tested permission. A disposable Standard execution received a random sentinel in its input. `DescribeExecution` recovered it from `input`, and `GetExecutionHistory` recovered it from the `ExecutionStarted` history event. The state machine, execution, and roles were deleted. Treat both permissions as **high** sensitive workflow-data reads.
+{% endhint %}
+
+`ListExecutions` is not a prerequisite. Execution ARNs occur in EventBridge events, CloudWatch logs, application databases, Step Functions console URLs, CloudTrail copies, CI output, incident artifacts, and parent-workflow data. With no AWS read permission, those same local sources—and saved workflow inputs or outputs—remain useful fallbacks. KMS-encrypted execution data can add a `kms:Decrypt` dependency.
+
+### Claim activity work with `states:GetActivityTask`
+
+An Activity worker long-polls a known activity ARN. `GetActivityTask` returns both the task input and a live task token, assigning that work item to the caller.[[22]](#references)
+
+```bash
+aws stepfunctions get-activity-task \
+ --activity-arn --worker-name audit-worker
+```
+
+{% hint style="danger" %}
+This was validated with a disposable Activity-backed workflow containing a random input sentinel. An STS session containing exactly `states:GetActivityTask` received the sentinel and a non-empty task token. The administrator failed the claimed task for cleanup and deleted the activity, state machine, execution, and roles. Treat the action as **high**: it reads queued workflow data and can disrupt a legitimate worker by claiming its task. Completing the task still requires a separate callback permission such as `states:SendTaskSuccess`.
+{% endhint %}
+
+Activity ARNs can be recovered from state-machine definitions, code, environment variables, worker configuration, logs, IaC, CloudTrail copies, or console URLs without `ListActivities`. A poll can wait up to 60 seconds and an empty response does not prove there are no future tasks. AWSPEASS reports this permission but must not poll the activity itself because claiming work has a side effect.
+
## References
- [1] [TestState - AWS Step Functions](https://docs.aws.amazon.com/step-functions/latest/apireference/API_TestState.html)
@@ -264,5 +315,7 @@ Because the added task stores its result and then transitions to the legitimate
- [18] [Processing input and output in Step Functions](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-input-output-filtering.html)
- [19] [UpdateStateMachine - AWS Step Functions](https://docs.aws.amazon.com/step-functions/latest/apireference/API_UpdateStateMachine.html)
- [20] [UpdateFunctionCode - AWS Lambda](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionCode.html)
+- [21] [GetExecutionHistory - AWS Step Functions](https://docs.aws.amazon.com/step-functions/latest/apireference/API_GetExecutionHistory.html)
+- [22] [GetActivityTask - AWS Step Functions](https://docs.aws.amazon.com/step-functions/latest/apireference/API_GetActivityTask.html)
{{#include ../../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ebs-privesc/README.md b/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ebs-privesc/README.md
index a5c1eeebdc..a81436e70d 100644
--- a/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ebs-privesc/README.md
+++ b/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ebs-privesc/README.md
@@ -18,6 +18,20 @@ Other permissions might also be useful, such as `ec2:DescribeInstances`, `ec2:De
The tool [https://github.com/Static-Flow/CloudCopy](https://github.com/Static-Flow/CloudCopy) performs this attack to **extract passwords from a domain controller**.[[7]](#references)
+```bash
+# ListSnapshotBlocks returns block indexes and short-lived BlockToken values.
+aws ebs list-snapshot-blocks --snapshot-id
+
+aws ebs get-snapshot-block --snapshot-id \
+ --block-index --block-token '' ./block.bin
+```
+
+{% hint style="danger" %}
+This was validated with a disposable 1 GiB direct-API snapshot containing a random sentinel in one 512 KiB block. A session containing exactly `ebs:ListSnapshotBlocks` and `ebs:GetSnapshotBlock` listed the block and recovered the sentinel bytes. Separately, `ebs:GetSnapshotBlock` alone recovered them when supplied a still-valid block token generated by another principal. The snapshot and roles were deleted. Treat the normal two-action chain as **critical** raw-disk access and `GetSnapshotBlock` as **high** when a token is already known.
+{% endhint %}
+
+The EC2 snapshot reaching `completed` does not guarantee immediate visibility through the EBS Direct API; the test observed a temporary `ResourceNotFoundException` and succeeded after bounded retries. If `ec2:DescribeSnapshots` is denied, snapshot IDs and block tokens may still exist in IaC, AMI metadata, CloudTrail, backup tooling, incident artifacts, shell history, or another compromised session. Tokens expire, encrypted snapshots can require KMS authorization, sparse blocks must be reconstructed at their indexes, and a token is a prerequisite rather than an authorization bypass.[[9]](#references)
+
**Potential Impact:** Indirect privesc by locating sensitive information in the snapshot (you could even recover Active Directory password hashes).[[7]](#references)[[8]](#references)
### **`ec2:CreateSnapshot`**
@@ -36,5 +50,6 @@ You can use this tool to automate the attack: [https://github.com/Static-Flow/Cl
- [6] [Share an Amazon EBS snapshot with other AWS accounts](https://docs.aws.amazon.com/ebs/latest/userguide/ebs-modifying-snapshot-permissions.html)
- [7] [CloudCopy](https://github.com/Static-Flow/CloudCopy)
- [8] [secretsdump.py](https://github.com/fortra/impacket/blob/master/examples/secretsdump.py)
+- [9] [ListSnapshotBlocks - EBS direct APIs](https://docs.aws.amazon.com/ebs/latest/APIReference/API_ListSnapshotBlocks.html)
{{#include ../../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-api-gateway-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-api-gateway-enum.md
index 05a0b359dd..6f2e358a3d 100644
--- a/src/pentesting-cloud/aws-security/aws-services/aws-api-gateway-enum.md
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-api-gateway-enum.md
@@ -221,6 +221,16 @@ print(response.text)
```
+#### `execute-api:Invoke` — tested IAM-protected application-data access
+
+`execute-api:Invoke` is a data-plane permission, not API Gateway management enumeration. It authorizes matching deployed REST, HTTP, or WebSocket routes, subject to method authorization, resource policies, explicit denies, and any additional application checks.[[11]](#references)[[12]](#references)
+
+{% hint style="danger" %}
+This was validated against a disposable regional REST API whose `GET /sensitive` method used `AWS_IAM` and returned a random sentinel from a mock integration. An unsigned request received `403`; a SigV4 request from an STS session containing only `execute-api:Invoke` recovered the exact sentinel. The API, deployment/stage, and role were deleted. Treat this permission as **high** application access. Do not call it automatically critical: impact depends on allowed method/resource ARNs and what those routes read or change.
+{% endhint %}
+
+The endpoint, stage, resource, and method do not require management-plane permissions when already known. Recover them from frontend/mobile code, SDK configuration, OpenAPI files, DNS/custom domains, CloudFormation outputs, application logs, documentation, browser history, error messages, or traffic captures. Try only read-only methods during enumeration unless the assessment explicitly authorizes application mutations. A `403` can also come from resource policy, SCP, VPC endpoint policy, signature problems, or an explicit deny; it is not proof that the identity lacks every invoke path.
+
### Custom Lambda Authorizer
A Lambda authorizer can authenticate a caller from a token or request parameters and **return an IAM policy** indicating whether the caller is **authorized to call the API method**. The authorizer must return a principal identifier and policy document; this example demonstrates a token-based REST authorizer.[[18]](#references)[[19]](#references)
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-appconfig-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-appconfig-enum.md
new file mode 100644
index 0000000000..11bf686497
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-appconfig-enum.md
@@ -0,0 +1,72 @@
+# AWS - AppConfig Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## AWS AppConfig
+
+AWS AppConfig, a capability of Systems Manager, stores and deploys application configuration independently from code. Its hierarchy is **application → environment → configuration profile → configuration version → deployment**. A hosted configuration profile keeps versioned content directly in AppConfig; other profile types point to sources such as S3, SSM Parameter Store, Secrets Manager, or CodePipeline.[[1]](#references)
+
+Hosted content may be JSON, YAML, text, feature flags, certificates, policy fragments, or arbitrary binary data. Teams sometimes put API keys, credentials, internal URLs, or customer configuration in it even though AWS recommends dedicated secret storage for secrets.
+
+### Enumeration
+
+```bash
+aws appconfig list-applications
+aws appconfig list-environments --application-id
+aws appconfig list-configuration-profiles --application-id
+aws appconfig list-hosted-configuration-versions \
+ --application-id \
+ --configuration-profile-id
+```
+
+### `appconfig:GetHostedConfigurationVersion` — tested configuration-body disclosure
+
+This control-plane API returns the complete immutable bytes for a specific hosted version; it does not require a deployment or the AppConfig Data retrieval-token workflow.[[2]](#references)
+
+```bash
+# Every ID and the version can be supplied directly; list permissions are optional.
+aws appconfig get-hosted-configuration-version \
+ --application-id \
+ --configuration-profile-id \
+ --version-number ./appconfig-content.bin
+
+file ./appconfig-content.bin
+strings ./appconfig-content.bin
+```
+
+{% hint style="danger" %}
+This was validated with an STS session policy containing only `appconfig:GetHostedConfigurationVersion`. A disposable hosted JSON version contained a unique random sentinel and the API returned its exact bytes. The version, profile, environment, application, and reader role were then deleted. Treat this action as **high** for hosted configuration disclosure. It does not retrieve data from an external S3, Parameter Store, or Secrets Manager profile and does not grant deployment permissions.
+{% endhint %}
+
+If AppConfig list calls are denied, recover the application ID, profile ID, and version from CloudFormation/CDK/Terraform, deployment logs, CloudTrail, source repositories, Lambda/ECS configuration, console URLs, local caches, or incident artifacts. Version numbers are positive integers, so test only versions in the authorized scope rather than assuming the latest one is the only sensitive revision. A profile that merely references another service still needs that service's own authorization unless its literal content is returned through a separately authorized AppConfig data-plane path.
+
+### AppConfig Data — deployed configuration disclosure
+
+The AppConfig Data API uses a two-step token flow. `appconfig:StartConfigurationSession` returns an initial token for a known application, environment, and profile; `appconfig:GetLatestConfiguration` exchanges that token for the currently deployed configuration bytes.[[3]](#references)[[4]](#references)
+
+```bash
+token=$(aws appconfigdata start-configuration-session \
+ --application-identifier \
+ --environment-identifier \
+ --configuration-profile-identifier \
+ --query InitialConfigurationToken --output text)
+
+# This CLI operation requires a positional output file.
+aws appconfigdata get-latest-configuration \
+ --configuration-token "$token" ./appconfig-data.bin
+```
+
+{% hint style="danger" %}
+This pair was validated with a disposable deployment containing a unique canary. The owning account recovered the exact deployed bytes. A different account authorized for the service actions received application-not-found, while two others were denied by IAM. The deployment, hosted version, profile, environment, application, and test role were deleted and verified absent. Treat the **pair** as high deployed-configuration access. Neither permission alone completes the normal retrieval path, and this expected same-account behavior is not a cross-account vulnerability.
+{% endhint %}
+
+If list calls are denied, the three identifiers can be recovered from AppConfig Agent settings, Lambda environment variables, ECS task definitions, Kubernetes manifests, application bootstrap configuration, IaC state, deployment logs, CloudTrail copies, and local agent caches. The data-plane request does not require the corresponding list operations.
+
+## References
+
+- [1] [What is AWS AppConfig?](https://docs.aws.amazon.com/appconfig/latest/userguide/what-is-appconfig.html)
+- [2] [GetHostedConfigurationVersion API](https://docs.aws.amazon.com/appconfig/2019-10-09/APIReference/API_GetHostedConfigurationVersion.html)
+- [3] [StartConfigurationSession API](https://docs.aws.amazon.com/appconfig/2019-10-09/APIReference/API_appconfigdata_StartConfigurationSession.html)
+- [4] [GetLatestConfiguration API](https://docs.aws.amazon.com/appconfig/2019-10-09/APIReference/API_appconfigdata_GetLatestConfiguration.html)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-appsync-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-appsync-enum.md
new file mode 100644
index 0000000000..f88021986f
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-appsync-enum.md
@@ -0,0 +1,70 @@
+# AWS - AppSync Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## AWS AppSync
+
+AWS AppSync hosts GraphQL and event APIs backed by data sources such as DynamoDB, Lambda, OpenSearch, RDS, HTTP endpoints, and `NONE` local resolvers. GraphQL APIs can authorize requests with IAM, Cognito user pools, OIDC, Lambda authorizers, or an **API key**; additional authorization modes may coexist on the same API.[[1]](#references)[[2]](#references)
+
+An AppSync API key is a bearer credential. Whoever knows its value can send requests allowed by the API's API-key authorization mode until the key expires or is deleted. Its practical impact is bounded by the schema, resolver authorization directives, and data sources exposed to that mode.
+
+### Enumeration
+
+```bash
+aws appsync list-graphql-apis
+aws appsync get-graphql-api --api-id
+aws appsync get-introspection-schema --api-id \
+ --format SDL ./schema.graphql
+aws appsync list-api-keys --api-id
+```
+
+### `appsync:ListApiKeys` — tested bearer-key theft and data access
+
+Despite its `List` name, `ListApiKeys` returns each active key's actual bearer value in `apiKeys[].id`, together with its description and expiration.[[3]](#references)
+
+```bash
+API_ID=
+API_KEY=$(aws appsync list-api-keys --api-id "$API_ID" \
+ --query 'apiKeys[?expires > `0`].id | [0]' --output text)
+
+# The GraphQL endpoint is commonly shipped in web/mobile client configuration.
+curl -sS '' \
+ -H 'content-type: application/json' \
+ -H "x-api-key: $API_KEY" \
+ --data '{"query":"query { knownSensitiveField }"}'
+```
+
+{% hint style="danger" %}
+This was validated end to end with an STS session restricted to `appsync:ListApiKeys`. A disposable API-key-authenticated GraphQL API exposed a random sentinel through a `NONE` resolver. The read returned a live key, and an HTTPS request carrying only that key in `x-api-key` retrieved the exact sentinel. The API, resolver, data source, key, and reader role were then deleted. Treat this action as **high**, not automatically critical: the stolen key can access only fields authorized for API-key callers.
+{% endhint %}
+
+`appsync:ListApiKeys` needs a known AppSync API ID, but not `appsync:ListGraphqlApis`. Obtain IDs and endpoints from web/mobile JavaScript and source maps, mobile application packages, `aws-exports.js`, Amplify configuration, IaC, source repositories, CI/CD logs, CloudTrail, console URLs, DNS/proxy history, error reports, or documentation. These are often available without any AWS permission because a legitimate client must know the endpoint and API-key-authenticated clients already embed a key.
+
+If schema introspection through GraphQL is enabled, use the stolen key to learn fields without `appsync:GetIntrospectionSchema`. If introspection is disabled, recover queries from frontend code, mobile binaries, network captures, generated GraphQL clients, tests, or documentation. A successful key listing is proof of credential disclosure; actual data impact still requires testing fields within the authorized assessment scope. Do not confuse the AppSync API ID with the API key in `apiKeys[].id`.
+
+### `appsync:GraphQL` — IAM-authorized application access
+
+For an API using `AWS_IAM`, `appsync:GraphQL` authorizes signed GraphQL fields. A field resource has the form `arn:aws:appsync:::apis//types//fields/`.[[2]](#references)[[4]](#references)
+
+```bash
+# awscurl signs the otherwise normal HTTPS GraphQL request with current AWS credentials.
+awscurl --service appsync --region \
+ -X POST -H 'content-type: application/json' \
+ -d '{"query":"query { knownSensitiveField }"}' \
+ 'https://.appsync-api..amazonaws.com/graphql'
+```
+
+{% hint style="danger" %}
+This was validated against a disposable IAM-authenticated GraphQL API. An STS session containing exactly `appsync:GraphQL` recovered a random sentinel from a `NONE` resolver; no AppSync management/list action or API key was present. The API and role were deleted. Treat this action as **high** application-data access. Its actual reach is bounded by allowed field ARNs, resolver authorization, schema operations, and downstream data-source controls.
+{% endhint %}
+
+The endpoint and valid queries are normally embedded in legitimate web/mobile clients, source maps, `aws-exports.js`, generated SDK code, tests, browser history, proxy captures, documentation, and error reports. These sources provide a permissionless fallback when AppSync enumeration is denied. Query only read fields during enumeration; the same IAM action can authorize mutations when their field ARNs are allowed.
+
+## References
+
+- [1] [What is AWS AppSync?](https://docs.aws.amazon.com/appsync/latest/devguide/what-is-appsync.html)
+- [2] [Security and authorization](https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html)
+- [3] [ListApiKeys API](https://docs.aws.amazon.com/appsync/latest/APIReference/API_ListApiKeys.html)
+- [4] [IAM authorization for AppSync GraphQL APIs](https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html#aws-iam-authorization)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-aurora-dsql-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-aurora-dsql-enum.md
new file mode 100644
index 0000000000..2a144913c5
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-aurora-dsql-enum.md
@@ -0,0 +1,33 @@
+# AWS - Aurora DSQL Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Basic information
+
+Amazon Aurora DSQL is a serverless distributed SQL database. Clusters support resource-based policies, including cross-account database-connect permissions.[[1]](#references)
+
+## Enumeration
+
+```bash
+aws dsql list-clusters
+aws dsql get-cluster --identifier
+aws dsql get-cluster-policy --identifier
+aws dsql list-tags-for-resource --resource-arn
+```
+
+When `ListClusters` is denied, recover cluster identifiers or ARNs from application connection settings, environment variables, IaC state, CI/CD output, CloudTrail copies, logs, or console URLs. Test `GetCluster` and `GetClusterPolicy` directly with known identifiers.
+
+## Post exploitation
+
+`dsql:PutClusterPolicy` on an owned cluster can be used to test whether a candidate external IAM principal is accepted during resource-policy validation. This is expected reconnaissance behavior, not victim access or a vulnerability. The operation replaces policy state and must not be performed by a read-only enumerator.
+
+{{#ref}}
+../aws-post-exploitation/aws-iam-post-exploitation/aws-resource-policy-principal-validation.md
+{{#endref}}
+
+## References
+
+- [1] [Aurora DSQL resource-based policy operations](https://docs.aws.amazon.com/aurora-dsql/latest/userguide/rbp-api-operations.html)
+- [2] [Aurora DSQL API reference](https://docs.aws.amazon.com/aurora-dsql/latest/APIReference/Welcome.html)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-batch-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-batch-enum.md
new file mode 100644
index 0000000000..3802d428af
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-batch-enum.md
@@ -0,0 +1,48 @@
+# AWS - Batch Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## AWS Batch
+
+AWS Batch schedules container jobs onto managed or unmanaged compute environments. A **job definition** is a versioned template containing the image, commands, environment variables, secrets references, mounts, resource requirements, execution role, job role, retry rules, and platform configuration used when a job is submitted.[[1]](#references)
+
+Job-definition revisions are immutable. Deregistration changes a revision to `INACTIVE`; AWS retains that control-plane history for a period, so an old revision may disclose configuration that has already been removed from the current active definition.[[2]](#references)
+
+### `batch:DescribeJobDefinitions` — tested environment disclosure
+
+`DescribeJobDefinitions` can filter by name, status, or exact ARN. The returned `containerProperties.environment` array contains literal environment-variable values, while `secrets` entries normally contain references rather than the protected secret value.[[3]](#references)
+
+```bash
+# Broad discovery when permitted.
+aws batch describe-job-definitions --status ACTIVE
+
+# No-list fallback: an exact name/revision ARN is enough.
+aws batch describe-job-definitions \
+ --job-definitions \
+ --query 'jobDefinitions[].{Arn:jobDefinitionArn,Status:status,Image:containerProperties.image,Command:containerProperties.command,Environment:containerProperties.environment,Secrets:containerProperties.secrets,JobRole:containerProperties.jobRoleArn,ExecutionRole:containerProperties.executionRoleArn}'
+
+# Check retained inactive revisions when their names are known.
+aws batch describe-job-definitions --job-definition-name --status INACTIVE
+```
+
+{% hint style="danger" %}
+This was validated with an STS session policy containing only `batch:DescribeJobDefinitions`. A disposable EC2-platform job definition contained a unique random sentinel as a plaintext container environment value; the response returned it exactly. No queue, compute environment, or job was created or run. The revision was deregistered and became `INACTIVE`, which is AWS Batch's supported teardown behavior. Treat this action as **high** for literal job configuration, but it does not allow job submission, role assumption, or dereferencing Secrets Manager/Parameter Store ARNs.
+{% endhint %}
+
+If name/list discovery is denied, find exact job-definition ARNs in CloudFormation/Terraform, Step Functions definitions, EventBridge targets, application deployment manifests, CloudTrail, CI/CD logs, source repositories, console URLs, shell history, or Batch job records accessible by another authorized path. Inspect all known revisions. Role ARNs, secret ARNs, and network identifiers are reconnaissance unless the response also contains reusable literal values.
+
+### Privilege escalation
+
+Submitting a job is a separate write path and can become privilege escalation when combined with a privileged job definition/role and the required queue access:
+
+{{#ref}}
+../aws-privilege-escalation/aws-batch-privesc/README.md
+{{#endref}}
+
+## References
+
+- [1] [AWS Batch job definitions](https://docs.aws.amazon.com/batch/latest/userguide/job_definitions.html)
+- [2] [DeregisterJobDefinition API](https://docs.aws.amazon.com/batch/latest/APIReference/API_DeregisterJobDefinition.html)
+- [3] [DescribeJobDefinitions API](https://docs.aws.amazon.com/batch/latest/APIReference/API_DescribeJobDefinitions.html)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-bedrock-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-bedrock-enum.md
index e07656a698..763829637e 100644
--- a/src/pentesting-cloud/aws-security/aws-services/aws-bedrock-enum.md
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-bedrock-enum.md
@@ -12,8 +12,48 @@ Amazon Bedrock is a fully managed service that makes it easy to build and scale
../aws-post-exploitation/aws-bedrock-post-exploitation/README.md
{{#endref}}
+Bedrock AgentCore's `bedrock-agentcore:PutResourcePolicy` can also validate candidate external IAM principals when used on an owned AgentCore resource. This expected policy-validation behavior is reconnaissance only, changes policy state, and must not be executed by read-only tooling.
+
+{{#ref}}
+../aws-post-exploitation/aws-iam-post-exploitation/aws-resource-policy-principal-validation.md
+{{#endref}}
+
+### AgentCore Identity — mint a workload token and recover stored API keys
+
+AgentCore Identity stores outbound API keys in a service-owned Secrets Manager secret. A manually created workload identity can request a workload access token, and that token can be exchanged for a credential-provider API key.[[2]](#references)[[3]](#references)
+
+```bash
+# UserId is caller supplied. Prefer the JWT flow in production; this flow
+# treats the value as opaque and relies on IAM for authorization.
+wat=$(aws bedrock-agentcore get-workload-access-token-for-user-id \
+ --workload-name \
+ --user-id \
+ --query workloadAccessToken --output text)
+
+# The response is the plaintext third-party API key. Do not print it in
+# routine enumeration output or send it to shared logs.
+aws bedrock-agentcore get-resource-api-key \
+ --workload-identity-token "$wat" \
+ --resource-credential-provider-name
+```
+
+The validated minimum path required all three permissions:
+
+- `bedrock-agentcore:GetWorkloadAccessTokenForUserId`
+- `bedrock-agentcore:GetResourceApiKey`
+- `secretsmanager:GetSecretValue` on the service-owned provider secret
+
+{% hint style="danger" %}
+This was tested with a disposable workload identity and API-key provider. An STS session restricted to exactly those three actions recovered the exact random canary key. Removing `secretsmanager:GetSecretValue` caused `GetResourceApiKey` to fail on the service-owned secret. A different AWS account authorized for the token API was rejected with `Workload Identity does not belong to caller account`. The workload identity and provider were deleted and verified absent; the service-owned secret entered AWS-managed deletion. Treat the complete chain as **critical credential disclosure**, not as a cross-account vulnerability.
+{% endhint %}
+
+AWS documents that it does not add another same-account binding between workload identities and credential providers: the IAM policy is the isolation control.[[4]](#references) Scope both the workload-identity and token-vault/provider ARNs, and constrain `bedrock-agentcore:userid` where the UserId flow is unavoidable. If list calls are denied, workload and provider names occur in AgentCore runtime/gateway configuration, IaC state, application source, environment variables, CloudTrail copies, SDK logs, and deployment artifacts.
+
## References
- [1] [Amazon Bedrock Documentation](https://aws.amazon.com/documentation-overview/bedrock/)
+- [2] [Get workload access token](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/get-workload-access-token.html)
+- [3] [GetResourceApiKey API](https://docs.aws.amazon.com/bedrock-agentcore/latest/APIReference/API_GetResourceApiKey.html)
+- [4] [Scope credential-provider access by workload identity](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/scope-credential-provider-access.html)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-cloudformation-and-codestar-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-cloudformation-and-codestar-enum.md
index 667e215fd5..e377d97300 100644
--- a/src/pentesting-cloud/aws-security/aws-services/aws-cloudformation-and-codestar-enum.md
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-cloudformation-and-codestar-enum.md
@@ -51,6 +51,61 @@ In the following page you can check how to **abuse cloudformation permissions to
Check for **secrets** or sensitive information in the **template, parameters & output** of each CloudFormation
+#### `DescribeStacks`, `GetTemplate`, and `GetTemplateSummary` — tested secret disclosure
+
+These three read actions expose different parts of a stack and must be checked independently:[[5]](#references)[[6]](#references)[[7]](#references)
+
+* `cloudformation:DescribeStacks` returns parameter values and outputs. Plain parameters and outputs can contain passwords, bootstrap tokens, API keys, endpoints, role names, and secret identifiers. A parameter declared with `NoEcho: true` is masked in stack descriptions, so do not claim that this action defeats `NoEcho`.
+* `cloudformation:GetTemplate` returns the deployed template body. It exposes hard-coded values in resources, metadata, mappings, defaults, and embedded scripts even when the caller cannot list stacks.
+* `cloudformation:GetTemplateSummary` returns template metadata and parameter declarations, including default values. A secret placed in a parameter default is therefore exposed without retrieving the full template body.
+
+```bash
+aws cloudformation describe-stacks --stack-name \
+ --query 'Stacks[0].{Parameters:Parameters,Outputs:Outputs}'
+
+aws cloudformation get-template --stack-name \
+ --query TemplateBody
+
+aws cloudformation get-template-summary --stack-name \
+ --query Parameters
+```
+
+{% hint style="danger" %}
+Each action above was tested separately through an STS session policy containing only that one action. A disposable stack stored a different random sentinel in template metadata, a parameter default/value, and an output. Each response recovered the relevant sentinel. The stack contained no compute and was deleted after the test. These actions are **high** when granted because real templates frequently contain deployment secrets; they are not automatically IAM privilege escalation.
+{% endhint %}
+
+`ListStacks` is only a discovery convenience. If listing is denied, recover a stack name or ARN from IaC repositories, CI logs, CloudTrail, deployment scripts, tags, error messages, or predictable framework names such as `CDKToolkit`, then call the specific read directly. If all CloudFormation reads are denied, local copies of templates and deployment output remain a permissionless fallback.
+
+#### `cloudformation:ListExports` — tested cross-stack output disclosure
+
+CloudFormation exports are named stack output values intended for consumption by other stacks. `ListExports` returns every visible export name, value, and exporting stack ID in the Region; it does not require a stack name or `ListStacks`.[[8]](#references) Exported passwords or tokens are an anti-pattern, but endpoints, identifiers, configuration fragments, and occasionally reusable secrets appear in real deployments.
+
+```bash
+aws cloudformation list-exports \
+ --query 'Exports[].{Name:Name,Value:Value,ExportingStackId:ExportingStackId}'
+```
+
+{% hint style="danger" %}
+This was validated with an STS session policy containing only `cloudformation:ListExports`. A disposable stack exported a unique random sentinel, and the action returned its exact value without stack-list or stack-describe permission. The stack used only a non-compute `AWS::CloudFormation::WaitConditionHandle` placeholder and was deleted with the reader role. Treat this action as **high** because it can disclose output values across stacks in one Region, but an ARN or endpoint alone is not a reusable credential.
+{% endhint %}
+
+Run the call in every enabled Region. If it is denied, known stack names can still be tested with independently authorized `DescribeStacks`; without AWS permissions, check IaC output declarations, deployment logs, shell history, generated `.env` files, CI artifacts, and local CloudFormation/CDK caches. Export names are often predictable (`--url`, VPC/subnet exports, and shared resource names), but guessing a name does not retrieve its value without another source.
+
+#### `cloudformation:DescribeChangeSet` — tested pending parameter disclosure
+
+A change set description includes its template parameters and proposed resource changes before execution.[[9]](#references)
+
+```bash
+aws cloudformation describe-change-set --change-set-name \
+ --query '{Stack:StackId,Parameters:Parameters,Changes:Changes,Status:Status}'
+```
+
+{% hint style="danger" %}
+This was validated with a disposable `CREATE` change set and an STS session containing exactly `cloudformation:DescribeChangeSet`. The response recovered a random plaintext parameter sentinel. A sibling parameter declared `NoEcho: true` remained masked, proving that the action does not bypass `NoEcho`. The unexecuted change set and review stack were deleted. Treat the permission as **high** because deployment parameters commonly contain bootstrap tokens, passwords, and connection strings when operators fail to mark them `NoEcho`.
+{% endhint %}
+
+`ListChangeSets` is optional when a name or ARN is known. Find identifiers in deployment output, CI/CD logs, CloudTrail copies, IaC tooling caches, console URLs, pull-request automation, or predictable deployment naming. If AWS access is denied, locally generated change-set JSON and CI artifacts provide a permissionless fallback.
+
## Codestar
AWS CodeStar was a service for creating, managing, and working with software development projects on AWS. Its project templates configured development and delivery resources, while role-based project access let teams add owners, contributors, and viewers.[[3]](#references) AWS discontinued support for creating and viewing CodeStar projects on July 31, 2024: the CodeStar console is unavailable and new projects cannot be created, but resources previously created by CodeStar—including source repositories, pipelines, and builds—continue to function.[[3]](#references)
@@ -84,6 +139,10 @@ In the following page you can check how to **abuse codestar permissions to escal
- [2] [AWS CLI CloudFormation command reference](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/)
- [3] [AWS CodeStar FAQ (AWS)](https://aws.amazon.com/es/codestar/faqs/)
- [4] [Actions, resources, and condition keys for AWS CodeStar](https://docs.aws.amazon.com/service-authorization/latest/reference/list_codestar.html)
+- [5] [DescribeStacks API](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_DescribeStacks.html)
+- [6] [GetTemplate API](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_GetTemplate.html)
+- [7] [GetTemplateSummary API](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_GetTemplateSummary.html)
+- [8] [ListExports API](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_ListExports.html)
+- [9] [DescribeChangeSet API](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_DescribeChangeSet.html)
{{#include ../../../banners/hacktricks-training.md}}
-
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-codeartifact-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-codeartifact-enum.md
new file mode 100644
index 0000000000..e1cb4d8601
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-codeartifact-enum.md
@@ -0,0 +1,40 @@
+# AWS - CodeArtifact Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Basic information
+
+AWS CodeArtifact stores private package versions and assets for ecosystems including generic packages, npm, PyPI, Maven, NuGet, Ruby, Swift, and Cargo. Assets can contain proprietary source, compiled code, configuration, build metadata, or secrets accidentally packaged with a release.[[1]](#references)
+
+## `codeartifact:GetPackageVersionAsset` — direct asset download
+
+The read-only action downloads a known asset without needing domain, repository, package, version, or asset-list permissions:[[2]](#references)
+
+```bash
+aws codeartifact get-package-version-asset \
+ --domain --domain-owner \
+ --repository --format \
+ --namespace --package \
+ --package-version --asset ./asset.bin
+```
+
+{% hint style="danger" %}
+This was validated with a disposable domain, repository, and generic package whose asset contained a random sentinel. An STS session containing exactly `codeartifact:GetPackageVersionAsset` downloaded and recovered the bytes. The package version, repository, domain, and role were deleted. Treat the permission as **high** private-code/artifact access.
+{% endhint %}
+
+If list actions are denied, recover coordinates from `package.json`, lock files, `pom.xml`, requirements/PyPI configuration, build logs, CI caches, IDE configuration, repository endpoints, source code, IaC, error messages, CloudTrail copies, or previously downloaded package metadata. Package-manager clients often expose every required coordinate locally. A CodeArtifact authorization token is not required when calling this API directly with AWS credentials authorized for the action.
+
+Test exact format and namespace rules: generic packages require a namespace, while other ecosystems map scopes/groups differently. KMS policies, domain ownership, repository policy, resource scope, and explicit denies can still constrain access.
+
+## Post exploitation
+
+`codeartifact:PutDomainPermissionsPolicy` on an owned domain can validate a candidate external IAM principal. This is expected resource-policy validation, not package access or cross-account compromise. Because the call replaces permissions-policy state, it must remain a manual technique and must never be executed by a read-only enumerator.
+
+{{#ref}}
+../aws-post-exploitation/aws-iam-post-exploitation/aws-resource-policy-principal-validation.md
+{{#endref}}
+
+## References
+
+- [1] [What is AWS CodeArtifact?](https://docs.aws.amazon.com/codeartifact/latest/ug/welcome.html)
+- [2] [GetPackageVersionAsset API](https://docs.aws.amazon.com/codeartifact/latest/APIReference/API_GetPackageVersionAsset.html)
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-cognito-enum/cognito-user-pools.md b/src/pentesting-cloud/aws-security/aws-services/aws-cognito-enum/cognito-user-pools.md
index 963dd1c20a..007748cb88 100644
--- a/src/pentesting-cloud/aws-security/aws-services/aws-cognito-enum/cognito-user-pools.md
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-cognito-enum/cognito-user-pools.md
@@ -43,6 +43,24 @@ aws cognito-idp describe-identity-provider \
--query 'IdentityProvider.ProviderDetails'
```
+**`cognito-idp:DescribeUserPoolClient`** likewise returns `ClientSecret` for a confidential user-pool app client.[[18]](#references)[[34]](#references) The secret is a live credential: depending on the enabled flows, it can calculate `SECRET_HASH` for user authentication or authenticate a machine client to the token endpoint.
+
+```bash
+aws cognito-idp describe-user-pool-client \
+ --user-pool-id --client-id \
+ --query 'UserPoolClient.{ClientId:ClientId,ClientSecret:ClientSecret,Flows:AllowedOAuthFlows,Scopes:AllowedOAuthScopes,AuthFlows:ExplicitAuthFlows}'
+
+# Example for a client configured for client_credentials.
+curl -sS -u ':' \
+ -H 'content-type: application/x-www-form-urlencoded' \
+ -d 'grant_type=client_credentials&scope=/' \
+ 'https://.auth..amazoncognito.com/oauth2/token'
+```
+
+{% hint style="danger" %}
+This was validated end to end with an STS session restricted to `cognito-idp:DescribeUserPoolClient`. A disposable confidential client enabled only the client-credentials flow. The action returned its secret, and the recovered client ID/secret obtained a real bearer access token from Cognito. The domain and complete user pool were deleted with the role. Treat this action as **high** credential disclosure; actual reach is bounded by the client's flows, scopes, resource servers, and downstream token validation.
+{% endhint %}
+
The pool ID is commonly present in frontend configuration, tokens, hosted-UI URLs, CloudFormation output, or ARNs. A username, group, or provider name recovered from those sources avoids needing the corresponding list permission.
**Potential Impact:** Bulk PII/account disclosure, targeted user reconnaissance, and theft of an upstream OAuth/OIDC client secret.
@@ -559,5 +577,6 @@ An error occurred (InvalidParameterException) when calling the GetCredentialsFor
- [31] [ListUsersInGroup](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUsersInGroup.html)
- [32] [AdminGetUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminGetUser.html)
- [33] [DescribeIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeIdentityProvider.html)
+- [34] [DescribeUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeUserPoolClient.html)
{{#include ../../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-connect-customer-profiles-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-connect-customer-profiles-enum.md
new file mode 100644
index 0000000000..2d619892bf
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-connect-customer-profiles-enum.md
@@ -0,0 +1,33 @@
+# AWS - Amazon Connect Customer Profiles Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Basic information
+
+Amazon Connect Customer Profiles stores consolidated customer records in named domains. Profiles can contain account numbers, names, birth dates, email addresses, telephone numbers, physical addresses, custom attributes, and keys imported from CRM, commerce, support, and contact-center systems.[[1]](#references)[[2]](#references)
+
+## `profile:SearchProfiles` — search customer PII
+
+The IAM prefix is `profile`, while the AWS CLI service name is `customer-profiles`. The API searches a known domain by up to five predefined or custom keys and returns the matching profile bodies.
+
+```bash
+aws customer-profiles search-profiles \
+ --domain-name \
+ --key-name _email \
+ --values ''
+```
+
+Useful predefined keys include `_profileId`, `_account`, `_fullName`, `_phone`, `_email`, `_assetId`, `_caseId`, `_orderId`, and identifiers from Salesforce, ServiceNow, Zendesk, Marketo, Segment, and Shopify.[[1]](#references)
+
+{% hint style="danger" %}
+This was validated with a disposable domain and profile containing unique account, email, phone, and name canaries. An STS session restricted to only `profile:SearchProfiles` found the profile and returned its PII. A different AWS account with the service action received an explicit error that the domain was not found in the caller's account; another account was denied by IAM. The profile and domain were deleted and verified absent. Treat `profile:SearchProfiles` as **high** customer-data disclosure for reachable domains, not as a cross-account vulnerability.
+{% endhint %}
+
+No domain-list permission is required. Domain names and searchable values occur in Connect integrations, Customer Profiles ARNs, application configuration, CRM mappings, IaC state, CloudTrail copies, support tooling, browser history, contact-flow exports, logs, and local customer-service applications. Exported CRM files, cached agent data, application logs, and browser storage are permissionless fallbacks when AWS calls are denied.
+
+## References
+
+- [1] [SearchProfiles API](https://docs.aws.amazon.com/connect/latest/APIReference/API_connect-customer-profiles_SearchProfiles.html)
+- [2] [Amazon Connect Customer Profiles actions and resources](https://docs.aws.amazon.com/service-authorization/latest/reference/list_customer-profiles.html)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-connect-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-connect-enum.md
new file mode 100644
index 0000000000..05af12dee9
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-connect-enum.md
@@ -0,0 +1,40 @@
+# AWS - Amazon Connect Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Basic information
+
+Amazon Connect provides cloud contact-center instances, users, queues, contacts, recordings, prompts, and agent workspaces. SAML-backed instances use `connect:GetFederationToken` to exchange an authorized AWS identity for short-lived Connect access and a sign-in URL.[[1]](#references)[[2]](#references)
+
+## Enumeration
+
+```bash
+aws connect list-instances
+aws connect list-users --instance-id
+aws connect list-security-profiles --instance-id
+aws connect list-routing-profiles --instance-id
+aws connect list-queues --instance-id
+```
+
+### `connect:GetFederationToken` — contact-center session access
+
+```bash
+# The response contains access and refresh tokens. Do not print it in routine
+# enumeration output or send it to shared logs.
+aws connect get-federation-token --instance-id
+```
+
+The token represents the matching Connect user, and that user's Connect security profiles determine access to contacts, customer data, recordings, prompts, agent tools, and administrative functions. The AWS permission alone does not create a Connect user or bypass the instance's identity mapping.
+
+{% hint style="danger" %}
+This was validated with a disposable SAML instance. The owning IAM user received a Connect federation token and user ARN. The instance deliberately contained Connect users whose names matched three external IAM principals; two external callers that had the service action still received `Instance not found`, while the other was denied by IAM. All users and the instance were deleted and verified absent. Treat `connect:GetFederationToken` as **high** session access to a reachable instance, not as an AWS cross-account vulnerability.
+{% endhint %}
+
+If `ListInstances` is denied, instance IDs appear in Connect ARNs, personalized sign-in URLs, browser history, SAML relay state, CloudTrail copies, application configuration, IaC state, support bundles, and agent desktop configuration. A known instance ID is sufficient for the token request; list access is not required.
+
+## References
+
+- [1] [GetFederationToken permissions and SAML setup](https://docs.aws.amazon.com/connect/latest/adminguide/configure-saml.html)
+- [2] [Amazon Connect actions and resources](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonconnect.html)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-datapipeline-codepipeline-codebuild-and-codecommit.md b/src/pentesting-cloud/aws-security/aws-services/aws-datapipeline-codepipeline-codebuild-and-codecommit.md
index 9952e8c30a..1a138b4f65 100644
--- a/src/pentesting-cloud/aws-security/aws-services/aws-datapipeline-codepipeline-codebuild-and-codecommit.md
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-datapipeline-codepipeline-codebuild-and-codecommit.md
@@ -54,6 +54,24 @@ aws codepipeline list-webhooks
aws codepipeline get-pipeline-state --name
```
+### `codepipeline:PollForJobs` — custom-action artifact credentials
+
+Third-party custom-action workers call `PollForJobs` with an action category, owner, provider, and version. When a matching pipeline action is ready, the job can include short-lived artifact credentials plus input-artifact locations.[[16]](#references)[[17]](#references)
+
+```bash
+aws codepipeline poll-for-jobs \
+ --action-type-id category=Test,owner=Custom,provider=,version=1 \
+ --max-batch-size 1
+```
+
+Treat every returned job as sensitive: do not print or persist the `artifactCredentials` object. In an isolated shell, use those credentials only to identify the session and read explicitly authorized canary artifacts.
+
+{% hint style="danger" %}
+This was validated with a disposable custom action and active pipeline. The owning account received a job, used its artifact credentials successfully with STS, and read the canary input artifact from S3. An external account that had `PollForJobs` received `ActionTypeNotFound` for the victim's custom action tuple. The pipeline, execution, custom action, role, versioned artifacts, and bucket were deleted and verified absent. Treat `codepipeline:PollForJobs` as **high** artifact access for a reachable custom action, not as a demonstrated cross-account vulnerability.
+{% endhint %}
+
+If pipeline and action listing is denied, action tuples occur in pipeline JSON, IaC state, worker configuration, build images, environment variables, deployment repositories, CloudTrail copies, and worker logs. Polling does not require `ListActionTypes` or `ListPipelines` when the tuple is already known.
+
### Privesc
In the following page you can check how to **abuse codepipeline permissions to escalate privileges**:
@@ -160,5 +178,7 @@ git -c credential.helper='!aws --profile codecommit credential-helper
- [13] [GetFile - AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/APIReference/API_GetFile.html)
- [14] [GetBlob - AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/APIReference/API_GetBlob.html)
- [15] [GetCommit - AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/APIReference/API_GetCommit.html)
+- [16] [PollForJobs API](https://docs.aws.amazon.com/codepipeline/latest/APIReference/API_PollForJobs.html)
+- [17] [Create a custom action for a pipeline](https://docs.aws.amazon.com/codepipeline/latest/userguide/how-to-create-custom-action.html)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-deadline-cloud-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-deadline-cloud-enum.md
new file mode 100644
index 0000000000..7a45f13090
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-deadline-cloud-enum.md
@@ -0,0 +1,56 @@
+# AWS - Deadline Cloud Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Basic information
+
+AWS Deadline Cloud organizes rendering work into farms, queues, fleets, workers, jobs, and tasks. Queues and fleets can reference IAM roles. Deadline's credential service assumes those roles and returns temporary STS credentials to authorized users or workers.[[1]](#references)
+
+## Enumeration
+
+```bash
+aws deadline list-farms
+aws deadline list-queues --farm-id
+aws deadline list-fleets --farm-id
+aws deadline get-queue --farm-id --queue-id
+aws deadline get-fleet --farm-id --fleet-id
+```
+
+### Queue-role credential vending
+
+The following actions return credentials for the IAM role configured on a reachable queue:
+
+- `deadline:AssumeQueueRoleForRead` returns credentials scoped for read access, including queue logs.
+- `deadline:AssumeQueueRoleForUser` returns credentials used by users and tools for job attachments and related queue operations.[[1]](#references)[[2]](#references)
+
+```bash
+aws deadline assume-queue-role-for-read \
+ --farm-id --queue-id
+
+aws deadline assume-queue-role-for-user \
+ --farm-id --queue-id
+```
+
+Handle the response as a secret. Export the returned access key, secret key, and session token into an isolated shell, then determine the real session identity before testing only authorized read targets:
+
+```bash
+AWS_ACCESS_KEY_ID='' \
+AWS_SECRET_ACCESS_KEY='' \
+AWS_SESSION_TOKEN='' \
+aws sts get-caller-identity
+```
+
+{% hint style="danger" %}
+Both APIs were validated against fresh disposable queues. Each returned usable STS credentials for the configured queue role to the owner. A different AWS account whose principal had both Deadline actions received farm-not-found; two other accounts were denied by IAM. All farms, queues, roles, buckets/objects, and generated log groups were deleted and verified absent. Treat either action as **high** role/data access when the queue is reachable. This expected credential-broker behavior is not itself a cross-account vulnerability.
+{% endhint %}
+
+The effective impact is bounded by the queue role and the session policy Deadline applies. An overprivileged queue role can therefore turn a queue-level permission into access to unrelated AWS data. AWS recommends binding the role trust to both the real account and farm with `aws:SourceAccount` and `aws:SourceArn`.[[1]](#references)
+
+If list permissions are denied, farm and queue IDs can still be recovered from Deadline ARNs, job-submission profiles, CloudWatch log-group names, CloudTrail copies, IaC state, workstation configuration, render-manager logs, and support bundles. Both IDs are sufficient for the credential request; list permissions are not required.
+
+## References
+
+- [1] [Deadline Cloud service roles](https://docs.aws.amazon.com/deadline-cloud/latest/userguide/security-iam-service-roles.html)
+- [2] [AssumeQueueRoleForRead API](https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_AssumeQueueRoleForRead.html)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-dynamodb-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-dynamodb-enum.md
index eb0f37573a..c6461747f2 100644
--- a/src/pentesting-cloud/aws-security/aws-services/aws-dynamodb-enum.md
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-dynamodb-enum.md
@@ -179,6 +179,14 @@ Therefore, a login like the previous one can be bypassed with something like:
# which is always true
```
+## Post exploitation
+
+`dynamodb:PutResourcePolicy` on an owned table can validate a candidate external IAM principal. This is expected policy validation, not access to an external DynamoDB table or account. DynamoDB policy updates are eventually consistent and rate constrained, and the call changes policy state, so it must not be part of automatic read-only enumeration.
+
+{{#ref}}
+../aws-post-exploitation/aws-iam-post-exploitation/aws-resource-policy-principal-validation.md
+{{#endref}}
+
## References
- [1] [What is Amazon DynamoDB?](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html)
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md b/src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md
index 9978448ddb..449b59ca84 100644
--- a/src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md
@@ -187,6 +187,28 @@ aws ssm describe-instance-patch-states --instance-ids
aws ssm describe-instance-associations-status --instance-id
```
+#### `ssm:GetDocument` — tested command-content disclosure
+
+Systems Manager documents are JSON or YAML programs used by Run Command, State Manager, Automation, and other SSM features. `GetDocument` returns the complete content of a known document version, including shell/PowerShell commands, parameters, download locations, and plugin inputs.[[28]](#references) Custom documents sometimes contain bootstrap tokens, internal URLs, credentials, or other plaintext operational data.
+
+```bash
+# ListDocuments is only a discovery convenience.
+aws ssm get-document --name \
+ --document-version '$DEFAULT' --document-format YAML \
+ --query '{Name:Name,Version:DocumentVersion,Content:Content}'
+
+# If the default version is uninteresting, try a version learned from IaC,
+# CloudTrail, deployment output, an association, or other local artifacts.
+aws ssm get-document --name \
+ --document-version
+```
+
+{% hint style="danger" %}
+This was validated with an STS session policy containing only `ssm:GetDocument`. A disposable custom Command document contained a unique random sentinel inside an `aws:runShellScript` command. `GetDocument` returned that exact sentinel in `Content`; the document was then deleted. Treat this permission as **high** because it can expose executable operational content, but it does not itself execute the document or grant access to referenced Secrets Manager/Parameter Store values.
+{% endhint %}
+
+If `ssm:ListDocuments` is denied, recover document names and versions from SSM associations, maintenance windows, CloudFormation/CDK/Terraform, source repositories, CloudTrail, command history, console URLs, deployment logs, or common organization naming conventions. AWS-owned public documents are normally not sensitive; prioritize account-owned documents and verify actual returned content.
+
You can check in an EC2 instance if Systems Manager is runnign just by executing:
```bash
@@ -324,6 +346,26 @@ aws autoscaling describe-load-balancer-target-groups
aws autoscaling describe-load-balancers
```
+### `autoscaling:DescribeLaunchConfigurations` — tested user-data disclosure
+
+The response includes the complete base64-encoded `UserData` stored in each legacy launch configuration, together with its image, instance profile, security groups, block devices, and instance settings.[[27]](#references) Bootstrap scripts commonly contain registration tokens, repository credentials, package-mirror passwords, internal URLs, or cloud credentials.
+
+```bash
+# Broad discovery when permitted
+aws autoscaling describe-launch-configurations --region
+
+# No-list fallback when a configuration name is already known
+aws autoscaling describe-launch-configurations \
+ --launch-configuration-names --region \
+ --query 'LaunchConfigurations[0].UserData' --output text | base64 -d
+```
+
+{% hint style="danger" %}
+This was tested through an STS session policy containing only `autoscaling:DescribeLaunchConfigurations`. A disposable launch configuration stored a unique random sentinel in its user data and launched no instance. The exact-action response returned the full blob; decoding it recovered the sentinel. The configuration and reader role were then deleted. Treat the action as **high** for bootstrap-secret disclosure, not as control of an already running instance.
+{% endhint %}
+
+A configuration name can be recovered from an Auto Scaling group, CloudFormation template, Elastic Beanstalk environment, ECS capacity provider, IaC, CloudTrail, deployment logs, or error output. If this API is denied, locally readable launch scripts and IaC are the permissionless fallback. Launch templates use the separate `ec2:DescribeLaunchTemplateVersions` path.
+
## Nitro
AWS Nitro is a suite of **innovative technologies** that form the underlying platform for AWS EC2 instances. Introduced by Amazon to **enhance security, performance, and reliability**, Nitro leverages custom **hardware components and a lightweight hypervisor**. It abstracts much of the traditional virtualization functionality to dedicated hardware and software, **minimizing the attack surface** and improving resource efficiency. By offloading virtualization functions, Nitro allows EC2 instances to deliver **near bare-metal performance**, making it particularly beneficial for resource-intensive applications. Additionally, the Nitro Security Chip specifically ensures the **security of the hardware and firmware**, further solidifying its robust architecture.[[20]](#references)
@@ -409,6 +451,38 @@ If a **VPN connection was stablished** you should search for **`.opvn`** config
../../aws-post-exploitation/aws-vpn-post-exploitation/README.md
{{#endref}}
+## Tested read-only data disclosures
+
+### `ec2:DescribeInstanceAttribute` — EC2 user data
+
+The `userData` instance attribute contains the original base64-encoded launch user data. Bootstrap scripts frequently contain repository tokens, activation keys, initial passwords, internal endpoints, or commands that reveal credential locations.[[29]](#references)
+
+```bash
+aws ec2 describe-instance-attribute \
+ --instance-id --attribute userData \
+ --query 'UserData.Value' --output text | base64 --decode
+```
+
+{% hint style="danger" %}
+This was validated while a disposable EC2 instance was still pending. An STS session containing exactly `ec2:DescribeInstanceAttribute` recovered a random sentinel from its launch user data. The instance reached `terminated`, its root volume was deleted, and the reader role was deleted. Treat this action as **high** secret-bearing bootstrap-data access.
+{% endhint %}
+
+`DescribeInstances` is not required if the instance ID is known. IDs appear in hostnames, logs, CloudTrail copies, SSM data, application monitoring, CI/CD output, IaC state, crash reports, shell history, or the instance metadata service available from the host. Stopped instances can still expose the attribute; an empty value is not proof that the caller lacks permission.
+
+### `ssm:GetOpsItem` — operational-data disclosure
+
+An OpsItem can contain incident descriptions and arbitrary `OperationalData` values.[[30]](#references)
+
+```bash
+aws ssm get-ops-item --ops-item-id
+```
+
+{% hint style="danger" %}
+This was validated with an STS session containing exactly `ssm:GetOpsItem`. A disposable OpsItem stored a random sentinel in a custom operational-data key and the action recovered it. `DeleteOpsItem` completed asynchronously; a final direct read returned `OpsItemNotFoundException`. Treat the action as **high** because incident records can contain customer data, internal resource details, investigation notes, credentials, or executable remediation context.
+{% endhint %}
+
+`DescribeOpsItems` is optional. IDs can be found in incident tickets, ChatOps messages, EventBridge events, automation output, logs, CloudTrail copies, console URLs, or local investigation notes without another AWS permission.
+
## References
- [1] [Getting started with Amazon EC2 orchestration using the Wizard - AWS Batch](https://docs.aws.amazon.com/batch/latest/userguide/getting-started-ec2.html)
@@ -437,5 +511,9 @@ If a **VPN connection was stablished** you should search for **`.opvn`** config
- [24] [What is Amazon EC2?](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts.html)
- [25] [Restrict access to Application Load Balancers](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/restrict-access-to-load-balancer.html)
- [26] [Restrict access with VPC origins](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-vpc-origins.html)
+- [27] [DescribeLaunchConfigurations API](https://docs.aws.amazon.com/autoscaling/ec2/APIReference/API_DescribeLaunchConfigurations.html)
+- [28] [GetDocument API](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_GetDocument.html)
+- [29] [DescribeInstanceAttribute API](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstanceAttribute.html)
+- [30] [GetOpsItem API](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_GetOpsItem.html)
{{#include ../../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-ec2-image-builder-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-ec2-image-builder-enum.md
new file mode 100644
index 0000000000..9c8e152cab
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-ec2-image-builder-enum.md
@@ -0,0 +1,44 @@
+# AWS - EC2 Image Builder Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## EC2 Image Builder
+
+EC2 Image Builder creates versioned machine-image pipelines from recipes, components, infrastructure configuration, and distribution settings. A **component** is a YAML or JSON document following the AWSTOE schema; its build and test phases can run shell or PowerShell commands while an image is assembled.[[1]](#references)[[2]](#references)
+
+This makes account-owned components security-sensitive even when the image pipeline is not running. They commonly encode package download URLs, repository credentials, bootstrap commands, license keys, internal endpoints, or tokens. Component versions are immutable, so older versions may retain values removed from the latest pipeline.
+
+### Enumeration
+
+```bash
+aws imagebuilder list-components --owner Self
+aws imagebuilder list-image-pipelines
+aws imagebuilder list-image-recipes --owner Self
+aws imagebuilder list-container-recipes --owner Self
+aws imagebuilder get-component --component-build-version-arn
+```
+
+### `imagebuilder:GetComponent` — tested component-source disclosure
+
+`GetComponent` returns metadata and the complete component document in `component.data`, including every build/test command and its literal arguments.[[3]](#references)
+
+```bash
+# ListComponents is only needed for discovery.
+aws imagebuilder get-component \
+ --component-build-version-arn \
+ --query 'component.{Name:name,Version:version,Platform:platform,Encrypted:encrypted,KmsKeyId:kmsKeyId,Data:data}'
+```
+
+{% hint style="danger" %}
+This was validated with an STS session restricted to `imagebuilder:GetComponent`. A disposable Linux component contained a unique random sentinel only in an `ExecuteBash` command; the response returned the exact sentinel in `component.data`. The component was then deleted and no image or build instance was launched. Treat this action as **high** for component source disclosure, but it does not execute commands or reveal the value of a secret merely referenced by ARN or environment-variable name.
+{% endhint %}
+
+When `imagebuilder:ListComponents` is denied, obtain component version ARNs from image recipes, CloudFormation/CDK/Terraform, CloudTrail, CI/CD output, source repositories, console URLs, image build logs, or naming conventions. Try specific historical versions learned from those artifacts because a component ARN includes the semantic version and build version. Prioritize owner `Self`; AWS-managed components are public and normally do not contain tenant data.
+
+## References
+
+- [1] [How EC2 Image Builder works](https://docs.aws.amazon.com/imagebuilder/latest/userguide/how-image-builder-works.html)
+- [2] [Create a custom build or test component with AWSTOE](https://docs.aws.amazon.com/imagebuilder/latest/userguide/create-component-yaml.html)
+- [3] [GetComponent API](https://docs.aws.amazon.com/imagebuilder/latest/APIReference/API_GetComponent.html)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-ecs-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-ecs-enum.md
index 0ed5130263..d2d96cf2f5 100644
--- a/src/pentesting-cloud/aws-security/aws-services/aws-ecs-enum.md
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-ecs-enum.md
@@ -101,6 +101,22 @@ Depending on the agent version, local cleanup settings, and workload churn, `str
- **Legacy agent configuration** — EC2 agent setups may use `ECS_ENGINE_AUTH_DATA` for Docker registry authentication; inspect the agent configuration separately because this setting is not evidence that the auth material is stored in `agent.db`.[[11]](#references)
- **Recently-stopped task containers** — local task and container records can include names, runtime IDs, statuses, and exit codes until the agent's configured cleanup removes them. These records are local state and may be useful even when the current `aws ecs describe-tasks` response no longer contains the same stopped task.[[11]](#references)[[14]](#references)[[15]](#references)
+### `ecs:DescribeTasks` — tested task-override disclosure
+
+`DescribeTasks` returns runtime task details, including container overrides supplied to `RunTask`. Plaintext command and environment overrides can contain API tokens, database credentials, tenant identifiers, or sensitive job input.[[7]](#references)[[21]](#references)
+
+```bash
+aws ecs describe-tasks --cluster \
+ --tasks \
+ --query 'tasks[].{Task:taskArn,Overrides:overrides,Containers:containers}'
+```
+
+{% hint style="danger" %}
+This was validated against a disposable Fargate task whose container override contained a random environment sentinel. An STS session containing exactly `ecs:DescribeTasks` recovered that plaintext value. The task was stopped, its task definition deleted, and its cluster deleted. Treat the action as **high** for runtime configuration disclosure; secret-store references remain references unless the caller separately reads the backing secret.
+{% endhint %}
+
+`ListTasks` is only a discovery convenience. Task and cluster ARNs appear in application logs, EventBridge events, CloudWatch log stream names, deployment output, CI/CD, CloudTrail copies, alarms, support artifacts, IaC state, and ECS console URLs. These are useful permissionless pivots. Stopped-task metadata is retained temporarily, so both live and recently stopped task ARNs are worth testing.
+
### Unauthenticated Access
{{#ref}}
@@ -149,5 +165,6 @@ In the following page you can check how to **abuse ECS permissions to escalate p
- [18] [Amazon ECS Agent network-interface model](https://raw.githubusercontent.com/aws/amazon-ecs-agent/master/ecs-agent/netlib/model/networkinterface/networkinterface.go)
- [19] [Best practices for IAM roles in Amazon ECS](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/security-iam-roles.html)
- [20] [Amazon ECS task definitions](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html)
+- [21] [DescribeTasks API](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_DescribeTasks.html)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-elastic-beanstalk-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-elastic-beanstalk-enum.md
index 4c05b0a3e9..a826d60477 100644
--- a/src/pentesting-cloud/aws-security/aws-services/aws-elastic-beanstalk-enum.md
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-elastic-beanstalk-enum.md
@@ -89,6 +89,30 @@ aws elasticbeanstalk describe-instances-health --environment-name # G
aws elasticbeanstalk describe-events
```
+#### `DescribeConfigurationSettings` — tested environment-secret disclosure
+
+Environment and saved-configuration option settings can include plaintext application environment variables. With a known application plus environment or configuration-template name, inspect them directly:[[21]](#references)
+
+```bash
+aws elasticbeanstalk describe-configuration-settings \
+ --application-name \
+ --environment-name \
+ --query 'ConfigurationSettings[].OptionSettings[?Namespace==`aws:elasticbeanstalk:application:environment`]'
+
+# Saved template variant
+aws elasticbeanstalk describe-configuration-settings \
+ --application-name \
+ --template-name
+```
+
+{% hint style="warning" %}
+The Beanstalk action alone was **not** sufficient in the live test. It failed first on `s3:CreateBucket`, then still failed when only `s3:GetObject` was added. The tested working set was `elasticbeanstalk:DescribeConfigurationSettings`, `s3:CreateBucket`, `s3:GetBucketLocation`, `s3:GetObject`, and `s3:ListBucket`. With that exact action set, a session recovered a random sentinel from `aws:elasticbeanstalk:application:environment`. Keep this as a **high-risk combination**; do not label `DescribeConfigurationSettings` alone high.
+{% endhint %}
+
+Elastic Beanstalk stores saved configuration templates in its regional account bucket, which explains the S3 authorization dependencies. In an account that actually has Beanstalk configuration, that bucket already exists; the tested Describe call was read-only and created no bucket. The disposable application/template were deleted, and the pre-existing regional bucket and unrelated objects were preserved.
+
+If Beanstalk or S3 listing is denied, application/environment names can still come from DNS (`*.elasticbeanstalk.com`), source repositories, `.elasticbeanstalk/config.yml`, CI/CD configuration, CloudFormation, CloudTrail, logs, or error messages. If direct S3 object access is independently granted, reading the saved template or application bundle from the known regional bucket is the simpler fallback.
+
### Unauthenticated Access
{{#ref}}
@@ -135,5 +159,6 @@ aws elasticbeanstalk describe-events
- [18] [CreateEnvironment - AWS Elastic Beanstalk API Reference](https://docs.aws.amazon.com/elasticbeanstalk/latest/api/API_CreateEnvironment.html)
- [19] [Deploying applications to Elastic Beanstalk environments](https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features.deploy-existing-version.html)
- [20] [elasticbeanstalk - AWS CLI Command Reference](https://docs.aws.amazon.com/cli/latest/reference/elasticbeanstalk/)
+- [21] [DescribeConfigurationSettings API](https://docs.aws.amazon.com/elasticbeanstalk/latest/api/API_DescribeConfigurationSettings.html)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-emr-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-emr-enum.md
index 64096fddf2..f764c76cbd 100644
--- a/src/pentesting-cloud/aws-security/aws-services/aws-emr-enum.md
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-emr-enum.md
@@ -46,6 +46,42 @@ aws emr list-security-configurations
aws emr list-studios #Get studio URLs
```
+## EMR Serverless
+
+EMR Serverless applications are durable control-plane objects for Spark or Hive workloads. An application selects an EMR release and can hold runtime configuration classifications and properties that are reused by jobs. No worker capacity is started merely by creating or describing an application.[[17]](#references)
+
+### `emr-serverless:GetApplication` — tested runtime-property disclosure
+
+`GetApplication` returns the named application's release, architecture, state, network settings, monitoring configuration, worker settings, and `runtimeConfiguration`.[[18]](#references) Runtime properties can include database endpoints, access tokens, passwords, or other plaintext values when operators put secrets directly in Spark/Hive configuration instead of using a secret store.
+
+```bash
+# ListApplications is optional when the ID is already known.
+aws emr-serverless get-application --application-id \
+ --query 'application.{Name:name,Type:type,State:state,Release:releaseLabel,Network:networkConfiguration,Runtime:runtimeConfiguration,Monitoring:monitoringConfiguration}'
+```
+
+{% hint style="danger" %}
+This was tested with an STS session policy containing only `emr-serverless:GetApplication`. A stopped disposable Spark application on `emr-7.10.0` stored a unique random sentinel in `runtimeConfiguration` under `spark-defaults`; `GetApplication` returned it exactly. The application was deleted without starting capacity or a job. Treat this action as **high** for embedded runtime configuration, but it does not grant access to referenced S3 objects, secrets, job output, or the application's execution role.
+{% endhint %}
+
+If `emr-serverless:ListApplications` is denied, application IDs can still be recovered from CloudFormation/Terraform, CloudTrail, CI/CD output, source repositories, monitoring links, job-run metadata available through another principal, or console URLs. A property name or secret ARN is useful reconnaissance but is not proof that its protected value was disclosed; inspect only literal values in the response.
+
+### `emr-serverless:GetJobRun` — tested job-argument disclosure
+
+`GetJobRun` returns the job driver, including Spark entry point and arguments or Hive query configuration, plus configuration overrides, execution-role ARN, monitoring locations, and failure details.[[19]](#references)
+
+```bash
+aws emr-serverless get-job-run \
+ --application-id --job-run-id \
+ --query 'jobRun.{Name:name,State:state,Driver:jobDriver,Overrides:configurationOverrides,Role:executionRole}'
+```
+
+{% hint style="danger" %}
+This was validated with an STS session containing exactly `emr-serverless:GetJobRun`. A disposable Spark job carried a random sentinel in `entryPointArguments`; the action recovered it before the deliberately invalid job failed. The application reached `TERMINATED`, its execution/reader roles were deleted, and no workers remained. Treat this permission as **high** because job arguments and overrides often contain tokens, database URLs, customer identifiers, or inline query data.
+{% endhint %}
+
+Neither `ListApplications` nor `ListJobRuns` is required when both IDs are known. Recover them from scheduler input, logs, CloudTrail copies, CI/CD output, monitoring URLs, event notifications, application databases, shell history, or console URLs. A returned S3 URI or secret ARN is a lead, not proof that its protected contents are readable without the corresponding permission.
+
#### Privesc
{{#ref}}
@@ -70,5 +106,8 @@ aws emr list-studios #Get studio URLs
- [14] [AWS CLI list-notebook-executions command reference](https://docs.aws.amazon.com/cli/latest/reference/emr/list-notebook-executions.html)
- [15] [AWS CLI list-security-configurations command reference](https://docs.aws.amazon.com/cli/latest/reference/emr/list-security-configurations.html)
- [16] [AWS CLI list-studios command reference](https://docs.aws.amazon.com/cli/latest/reference/emr/list-studios.html)
+- [17] [What is Amazon EMR Serverless?](https://docs.aws.amazon.com/emr/latest/EMR-Serverless-UserGuide/emr-serverless.html)
+- [18] [GetApplication API](https://docs.aws.amazon.com/emr-serverless/latest/APIReference/API_GetApplication.html)
+- [19] [GetJobRun API](https://docs.aws.amazon.com/emr-serverless/latest/APIReference/API_GetJobRun.html)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-greengrass-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-greengrass-enum.md
new file mode 100644
index 0000000000..822bb9d761
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-greengrass-enum.md
@@ -0,0 +1,31 @@
+# AWS - IoT Greengrass Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Basic information
+
+AWS IoT Greengrass V2 deploys component recipes and artifacts to edge devices. Lambda-backed components package a published Lambda version as an artifact, so the bundle can contain proprietary source, binaries, configuration, or accidentally embedded secrets.[[1]](#references)
+
+## `greengrass:GetComponentVersionArtifact` — presigned component download
+
+For a known public or Lambda component version ARN and artifact name, this action returns an S3 presigned URL:[[2]](#references)
+
+```bash
+url="$(aws greengrassv2 get-component-version-artifact \
+ --arn '' --artifact-name '' \
+ --query preSignedUrl --output text)"
+curl --fail --location "$url" --output component.zip
+```
+
+The artifact name is the portion after the scheme in the component recipe's artifact URI. If `greengrass:GetComponent` is also allowed, download the recipe to obtain it; otherwise use local deployment recipes, Greengrass caches, logs, device configuration, IaC, build output, CloudTrail copies, or CI/CD artifacts.
+
+{% hint style="danger" %}
+This was validated end to end with a disposable Lambda-backed private component. Its Lambda ZIP contained a random source-code sentinel. An STS session containing exactly `greengrass:GetComponentVersionArtifact` obtained the presigned URL, and downloading the ZIP without AWS credentials recovered the sentinel. The component, all Lambda versions/function, and roles were deleted. Treat the action as **high** component-code access.
+{% endhint %}
+
+The same API did **not** retrieve an ordinary private component backed by an arbitrary S3 URI; AWS documents this operation for public or Lambda components. Do not generalize the result to every private S3 component. Presigned URLs expire, and retrieving referenced external artifacts can require separate S3/KMS authorization.
+
+## References
+
+- [1] [Develop AWS IoT Greengrass components](https://docs.aws.amazon.com/greengrass/v2/developerguide/develop-greengrass-components.html)
+- [2] [GetComponentVersionArtifact API](https://docs.aws.amazon.com/greengrass/v2/APIReference/API_GetComponentVersionArtifact.html)
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-iot-core-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-iot-core-enum.md
new file mode 100644
index 0000000000..dffc34f529
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-iot-core-enum.md
@@ -0,0 +1,35 @@
+# AWS - IoT Core Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Basic information
+
+AWS IoT Core represents devices as **things**. A thing can have a classic shadow and named shadows: JSON documents whose `desired`, `reported`, and metadata sections retain device or application state even while the device is offline.[[1]](#references) Shadows commonly contain operational values, identifiers, locations, endpoints, or application data, so reading one can disclose sensitive information without controlling the device.
+
+## Read a device shadow
+
+The read-only **`iot:GetThingShadow`** permission returns a known thing's classic shadow. The data-plane endpoint is account- and region-specific:
+
+```bash
+endpoint="$(aws iot describe-endpoint --endpoint-type iot:Data-ATS --query endpointAddress --output text)"
+aws iot-data get-thing-shadow \
+ --endpoint-url "https://${endpoint}" \
+ --thing-name \
+ shadow.json
+cat shadow.json
+```
+
+For a named shadow, add `--shadow-name `.[[2]](#references)
+
+{% hint style="danger" %}
+This was validated end to end with a disposable thing whose classic shadow contained a random sentinel in `state.reported`. An STS session containing exactly `iot:GetThingShadow` recovered the sentinel through the IoT data endpoint. The shadow, thing, and role were deleted. Treat this permission as **high** data access when its resource scope reaches production things.
+{% endhint %}
+
+If management enumeration is denied, the endpoint, region, thing name, and shadow name can often be recovered without further AWS permissions from device firmware, mobile or desktop clients, configuration files, certificates and their filenames, source code, infrastructure-as-code, logs, packet captures, or application URLs. `iot:DescribeEndpoint`, `iot:ListThings`, and `iot:ListNamedShadowsForThing` help when allowed, but are not prerequisites if the identifiers are already known.
+
+An empty or missing shadow is not proof that the permission is harmless: test the correct region, classic versus named shadow, and exact resource ARN. Device policies, IAM policies, VPC/network access, and explicit denies can still constrain the request.
+
+## References
+
+- [1] [AWS IoT Device Shadow service](https://docs.aws.amazon.com/iot/latest/developerguide/iot-device-shadows.html)
+- [2] [GetThingShadow API](https://docs.aws.amazon.com/iot/latest/apireference/API_iotdata_GetThingShadow.html)
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-iot-wireless-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-iot-wireless-enum.md
new file mode 100644
index 0000000000..3aa73b36e8
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-iot-wireless-enum.md
@@ -0,0 +1,48 @@
+# AWS - IoT Wireless Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Basic information
+
+AWS IoT Wireless manages LoRaWAN and Amazon Sidewalk devices, device profiles, service profiles, and destinations. A Sidewalk device record can contain the certificates and private onboarding keys used by the physical device, so its read API is materially more sensitive than ordinary inventory metadata.[[1]](#references)[[2]](#references)
+
+## Enumeration
+
+```bash
+aws iotwireless list-wireless-devices
+aws iotwireless list-device-profiles
+aws iotwireless list-service-profiles
+aws iotwireless list-destinations
+```
+
+### `iotwireless:GetWirelessDevice` — Sidewalk private-key disclosure
+
+For a known device ID, the read-only API returns the device configuration. For a provisioned Sidewalk device, this can include `Sidewalk.PrivateKeys` and `Sidewalk.DeviceCertificates`:[[1]](#references)[[2]](#references)
+
+```bash
+# Avoid printing key material during normal enumeration.
+aws iotwireless get-wireless-device \
+ --identifier \
+ --identifier-type WirelessDeviceId \
+ --query '{Arn:Arn,Name:Name,Status:Sidewalk.Status,PrivateKeyCount:length(Sidewalk.PrivateKeys),CertificateCount:length(Sidewalk.DeviceCertificates)}'
+
+# Retrieve the full response only into an approved secret-handling workflow.
+aws iotwireless get-wireless-device \
+ --identifier \
+ --identifier-type WirelessDeviceId
+```
+
+{% hint style="danger" %}
+This was validated end to end with a disposable Sidewalk profile, destination, and device. `GetWirelessDevice` returned two private onboarding keys and two certificates to the owning account. Calls from two other AWS accounts that had the service action returned `WirelessDevice record not found`; another caller was denied by IAM. The device, profile, destination, and role were deleted and verified absent. Treat `iotwireless:GetWirelessDevice` as **high** credential access for reachable Sidewalk devices, not as an AWS cross-account vulnerability.
+{% endhint %}
+
+If list permissions are denied, recover the device ID from IoT Wireless ARNs, CloudTrail copies, IaC state, deployment scripts, manufacturing/provisioning systems, support bundles, application logs, or local device configuration. `GetWirelessDevice` also accepts a DevEUI, Thing name, or Sidewalk manufacturing serial number when the corresponding identifier type is supplied.[[1]](#references)
+
+Failed create calls are not sufficient cleanup evidence. In testing, one `CreateDeviceProfile` call returned `ConflictException` after the profile had actually appeared. Reconcile test resources by unique name/tag after failures as well as by IDs returned from successful calls.
+
+## References
+
+- [1] [GetWirelessDevice API](https://docs.aws.amazon.com/iot-wireless/latest/apireference/API_GetWirelessDevice.html)
+- [2] [SidewalkDevice API type](https://docs.aws.amazon.com/iot-wireless/latest/apireference/API_SidewalkDevice.html)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-kinesis-data-streams-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-kinesis-data-streams-enum.md
new file mode 100644
index 0000000000..ef00842d58
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-kinesis-data-streams-enum.md
@@ -0,0 +1,47 @@
+# AWS - Kinesis Data Streams Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Basic information
+
+Amazon Kinesis Data Streams stores ordered records in shards for a configured retention period. A consumer obtains a short-lived shard iterator and repeatedly calls `GetRecords`; the response includes both records and the next iterator.[[1]](#references)[[2]](#references) Stream records may contain application events, telemetry, audit data, personal data, or credentials accidentally placed on the stream.
+
+## Read stream records
+
+The normal read chain needs **`kinesis:GetShardIterator`** and **`kinesis:GetRecords`**:
+
+```bash
+aws kinesis list-shards --stream-name
+
+iterator="$(aws kinesis get-shard-iterator \
+ --stream-name \
+ --shard-id \
+ --shard-iterator-type TRIM_HORIZON \
+ --query ShardIterator --output text)"
+
+aws kinesis get-records --shard-iterator "$iterator"
+```
+
+`GetRecords` returns base64-encoded `Data`. Continue with the returned `NextShardIterator` when the first response is empty; `LATEST` only observes records written after the iterator was created, while `TRIM_HORIZON` begins at the oldest retained record.[[2]](#references)
+
+{% hint style="danger" %}
+This was validated with a disposable stream containing a random sentinel. A session containing exactly `kinesis:GetShardIterator` and `kinesis:GetRecords` recovered it. Separately, a session containing only `kinesis:GetRecords` recovered the same record when supplied a still-valid iterator created by another principal. The stream and roles were deleted. Treat `kinesis:GetRecords` as **high** data access. `GetShardIterator` alone does not return records and should not be promoted by itself.
+{% endhint %}
+
+If `ListStreams` or `ListShards` is denied, stream names and shard IDs can often be found without further AWS permissions in application configuration, Lambda event-source mappings, Firehose definitions, source code, infrastructure-as-code, logs, metrics labels, CloudTrail copies, consumer checkpoints, or error messages. A leaked iterator is temporary but is sufficient for `GetRecords` while valid, so do not assume the list and iterator actions are mandatory prerequisites.
+
+Resource policies, IAM policies, KMS configuration, retention, iterator expiry, and explicit denies affect real reach. Preserve the partition key, sequence number, and approximate arrival time when recording evidence.
+
+## Post exploitation
+
+`kinesis:PutResourcePolicy` on an owned stream can validate a candidate external IAM principal. The tested success/error difference is expected policy validation; it does not read or write the external account. The operation changes policy state and is not appropriate for automatic read-only enumeration.
+
+{{#ref}}
+../aws-post-exploitation/aws-iam-post-exploitation/aws-resource-policy-principal-validation.md
+{{#endref}}
+
+## References
+
+- [1] [GetShardIterator API](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_GetShardIterator.html)
+- [2] [GetRecords API](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_GetRecords.html)
+- [3] [Kinesis Data Streams terminology and concepts](https://docs.aws.amazon.com/streams/latest/dev/key-concepts.html)
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-lex-v2-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-lex-v2-enum.md
new file mode 100644
index 0000000000..75d73d7ccb
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-lex-v2-enum.md
@@ -0,0 +1,49 @@
+# AWS - Lex V2 Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Basic information
+
+Amazon Lex V2 stores conversational bots as locales, intents, slots, utterances, prompts, and related configuration. Its export workflow packages a bot, version, or bot resource into an archive and returns a temporary download URL when the export completes.[[1]](#references)[[2]](#references)
+
+## Enumeration
+
+```bash
+aws lexv2-models list-bots
+aws lexv2-models list-bot-locales --bot-id --bot-version DRAFT
+aws lexv2-models list-intents \
+ --bot-id --bot-version DRAFT --locale-id
+aws lexv2-models list-exports
+```
+
+### Export a complete bot definition
+
+`lex:CreateExport` starts the export and `lex:DescribeExport` returns status and the presigned download URL. The URL is a bearer secret until it expires.
+
+```bash
+export_id=$(aws lexv2-models create-export \
+ --resource-specification \
+ '{"botExportSpecification":{"botId":"","botVersion":"DRAFT"}}' \
+ --file-format LexJson \
+ --query exportId --output text)
+
+aws lexv2-models describe-export --export-id "$export_id" \
+ --query '{Status:exportStatus,FailureReasons:failureReasons}'
+
+# Once status is Completed, retrieve downloadUrl only inside an approved
+# secret-handling workflow and download it before it expires.
+aws lexv2-models describe-export --export-id "$export_id"
+```
+
+{% hint style="danger" %}
+This workflow was validated end to end with a disposable bot. The owning account completed the export and downloaded a 523-byte bot archive. An external account authorized for the Lex service call received resource-not-found for the victim bot; two other accounts were denied by IAM. The export, bot, and role were deleted and verified absent. Treat the **CreateExport + DescribeExport** workflow as high bot-definition disclosure for reachable bots, not as a cross-account vulnerability.
+{% endhint %}
+
+An already existing export can make `DescribeExport` sufficient to recover its download URL when the export ID is known. Without list access, recover bot/export IDs from Lex ARNs, console URLs, application configuration, IaC state, deployment logs, CloudTrail copies, CI output, or support bundles. Bot IDs are also embedded in many runtime integration configurations.
+
+## References
+
+- [1] [CreateExport API](https://docs.aws.amazon.com/lexv2/latest/APIReference/API_CreateExport.html)
+- [2] [DescribeExport API](https://docs.aws.amazon.com/lexv2/latest/APIReference/API_DescribeExport.html)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-managed-flink-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-managed-flink-enum.md
new file mode 100644
index 0000000000..f793c4a23e
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-managed-flink-enum.md
@@ -0,0 +1,40 @@
+# AWS - Managed Service for Apache Flink Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Managed Service for Apache Flink
+
+Amazon Managed Service for Apache Flink, formerly Kinesis Data Analytics for Apache Flink, runs streaming applications while AWS manages their compute resources. Its control-plane application object identifies the code location, runtime, execution role, network configuration, checkpoints, monitoring, and application properties.[[1]](#references)
+
+Application properties are grouped key/value maps supplied to the Flink application at runtime. Teams may put broker credentials, API tokens, database passwords, internal endpoints, or other configuration directly in these maps, so describing a stopped application can expose data without starting compute.
+
+### Enumeration
+
+```bash
+aws kinesisanalyticsv2 list-applications
+aws kinesisanalyticsv2 describe-application --application-name
+```
+
+### `kinesisanalytics:DescribeApplication` — tested property disclosure
+
+Although the CLI namespace is `kinesisanalyticsv2`, the IAM service prefix remains `kinesisanalytics`. The response's `ApplicationConfigurationDescription.EnvironmentPropertyDescriptions.PropertyGroupDescriptions[].PropertyMap` contains the configured literal application properties.[[2]](#references)
+
+```bash
+# ListApplications is optional when the application name is already known.
+aws kinesisanalyticsv2 describe-application \
+ --application-name \
+ --query 'ApplicationDetail.{Name:ApplicationName,Status:ApplicationStatus,Runtime:RuntimeEnvironment,Role:ServiceExecutionRole,Properties:ApplicationConfigurationDescription.EnvironmentPropertyDescriptions.PropertyGroupDescriptions,Code:ApplicationConfigurationDescription.ApplicationCodeConfigurationDescription,Vpc:ApplicationConfigurationDescription.VpcConfigurationDescriptions}'
+```
+
+{% hint style="danger" %}
+This was validated with an STS session policy containing only `kinesisanalytics:DescribeApplication`. A disposable Flink 1.20 application was never started and held a unique random sentinel only in an environment property map; `DescribeApplication` returned it exactly. The application and its unused service role were then deleted. Treat this action as **high** for literal application-property disclosure, but it does not grant access to referenced S3 code, streams, VPC resources, or the service execution role.
+{% endhint %}
+
+If `kinesisanalytics:ListApplications` is denied, recover the application name from CloudFormation/Terraform, CloudTrail, CI/CD logs, source repositories, CloudWatch log configuration, console URLs, tags available through another path, or naming conventions. Configuration may contain only endpoints or secret references; those are leads, whereas only returned literal secret material is an immediate disclosure.
+
+## References
+
+- [1] [What is Amazon Managed Service for Apache Flink?](https://docs.aws.amazon.com/managed-flink/latest/java/what-is.html)
+- [2] [DescribeApplication API](https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_DescribeApplication.html)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-managed-prometheus-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-managed-prometheus-enum.md
new file mode 100644
index 0000000000..51310fa5a5
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-managed-prometheus-enum.md
@@ -0,0 +1,36 @@
+# AWS - Managed Service for Prometheus Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Basic information
+
+Amazon Managed Service for Prometheus (AMP, API namespace `aps`) is a serverless Prometheus-compatible monitoring service. Workspaces can contain operational metrics, labels, alerting rules, and alert-manager configuration.[[1]](#references)
+
+## Enumeration
+
+```bash
+aws amp list-workspaces
+aws amp describe-workspace --workspace-id
+aws amp describe-resource-policy --workspace-id
+aws amp list-rule-groups-namespaces --workspace-id
+aws amp describe-alert-manager-definition --workspace-id
+aws amp describe-logging-configuration --workspace-id
+aws amp list-scrapers
+```
+
+If list operations are denied, obtain workspace IDs from remote-write URLs, Prometheus configuration, EKS collector configuration, Grafana data sources, IaC state, CloudTrail copies, logs, or console URLs, then try the corresponding `Describe*` operations directly.
+
+## Post exploitation
+
+`aps:PutResourcePolicy` on an owned workspace can validate candidate external IAM principals. The tested success/error difference is expected policy validation; it neither queries the external workspace nor compromises the named account. This write action must remain a manual, explicitly authorized technique.
+
+{{#ref}}
+../aws-post-exploitation/aws-iam-post-exploitation/aws-resource-policy-principal-validation.md
+{{#endref}}
+
+## References
+
+- [1] [Amazon Managed Service for Prometheus documentation](https://docs.aws.amazon.com/prometheus/)
+- [2] [How AMP works with IAM](https://docs.aws.amazon.com/prometheus/latest/userguide/security_iam_service-with-iam.html)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-mediapackage-v2-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-mediapackage-v2-enum.md
new file mode 100644
index 0000000000..27444d620f
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-mediapackage-v2-enum.md
@@ -0,0 +1,37 @@
+# AWS - MediaPackage v2 Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Basic information
+
+AWS Elemental MediaPackage v2 ingests and packages live video. Its hierarchy includes channel groups, channels, and origin endpoints; channel and origin-endpoint policies control data-plane access.[[1]](#references)
+
+## Enumeration
+
+```bash
+aws mediapackagev2 list-channel-groups
+aws mediapackagev2 list-channels --channel-group-name
+aws mediapackagev2 get-channel \
+ --channel-group-name --channel-name
+aws mediapackagev2 get-channel-policy \
+ --channel-group-name --channel-name
+aws mediapackagev2 list-origin-endpoints \
+ --channel-group-name --channel-name
+```
+
+When list access is denied, channel-group and channel names may be present in contribution endpoints, encoder configuration, IaC, deployment output, monitoring, logs, CloudTrail copies, or console URLs. Query known names directly.
+
+## Post exploitation
+
+`mediapackagev2:PutChannelPolicy` on an owned channel can validate candidate external IAM principals. This is expected policy validation and reveals only whether the candidate is accepted; it does not access external media or modify the named account. The call replaces policy state and is unsuitable for automatic read-only enumeration.
+
+{{#ref}}
+../aws-post-exploitation/aws-iam-post-exploitation/aws-resource-policy-principal-validation.md
+{{#endref}}
+
+## References
+
+- [1] [AWS Elemental MediaPackage v2 API reference](https://docs.aws.amazon.com/mediapackage/latest/APIReference/Welcome.html)
+- [2] [`PutChannelPolicy`](https://docs.aws.amazon.com/mediapackage/latest/APIReference/API_PutChannelPolicy.html)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-q-in-connect-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-q-in-connect-enum.md
new file mode 100644
index 0000000000..b7f72e8a8e
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-q-in-connect-enum.md
@@ -0,0 +1,42 @@
+# AWS - Amazon Q in Connect Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Basic information
+
+Amazon Q in Connect, whose IAM service prefix remains `wisdom`, can store custom knowledge-base content such as plain text, HTML, CSV, PDF, and Word documents. `GetContent` returns metadata and a temporary presigned URL for the underlying content.[[1]](#references)[[2]](#references)
+
+## Enumeration
+
+```bash
+aws wisdom list-knowledge-bases
+aws wisdom list-contents --knowledge-base-id
+aws wisdom get-content-summary \
+ --knowledge-base-id --content-id
+```
+
+### `wisdom:GetContent` — download knowledge-base documents
+
+```bash
+# Avoid printing the whole response in shared output because content.url is a
+# bearer URL. Capture it only inside an approved secret-handling workflow.
+url=$(aws wisdom get-content \
+ --knowledge-base-id \
+ --content-id \
+ --query content.url --output text)
+
+curl --fail --silent --show-error "$url" --output ./q-connect-content.bin
+```
+
+{% hint style="danger" %}
+This was validated end to end with a disposable custom knowledge base and unique text canary. An STS session restricted to only `wisdom:GetContent` received a working presigned URL and downloaded the exact bytes. A different AWS account with the service action received knowledge-base-not-found, while another was denied by IAM. The content and knowledge base were deleted and verified absent. Treat `wisdom:GetContent` as **high** document disclosure for reachable content, not as a cross-account vulnerability.
+{% endhint %}
+
+`ListKnowledgeBases` and `ListContents` are discovery conveniences, not prerequisites. Knowledge-base and content IDs occur in ARNs, Connect/Q integration configuration, application source, browser URLs, IaC state, CloudTrail copies, agent logs, support bundles, and search results. Local downloads, browser caches, exported knowledge articles, synced source repositories, and workstation configuration remain permissionless fallbacks.
+
+## References
+
+- [1] [StartContentUpload API and supported document types](https://docs.aws.amazon.com/connect/latest/APIReference/API_amazon-q-connect_StartContentUpload.html)
+- [2] [Amazon Q in Connect actions and resources](https://docs.aws.amazon.com/service-authorization/latest/reference/list_q-in-connect.html)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-route53-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-route53-enum.md
index 1eeb08c693..996ada3dcf 100644
--- a/src/pentesting-cloud/aws-security/aws-services/aws-route53-enum.md
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-route53-enum.md
@@ -24,6 +24,14 @@ aws route53 list-health-checks
aws route53 list-traffic-policies
```
+### Post-exploitation account-ID validation
+
+On an owned Route 53 Resolver DNS Firewall rule group, `route53resolver:PutFirewallRuleGroupPolicy` can distinguish an allocated account ID from an unallocated control. This is expected policy-validation behavior and confirms only account allocation; it does not provide DNS access or affect the candidate account. The call changes policy state and must remain manual.
+
+{{#ref}}
+../aws-post-exploitation/aws-iam-post-exploitation/aws-resource-policy-principal-validation.md
+{{#endref}}
+
### Privesc
{{#ref}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-s3-athena-and-glacier-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-s3-athena-and-glacier-enum.md
index 9c0226eb61..6e5d0314dd 100644
--- a/src/pentesting-cloud/aws-security/aws-services/aws-s3-athena-and-glacier-enum.md
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-s3-athena-and-glacier-enum.md
@@ -261,6 +261,35 @@ In the following page you can check how to **abuse S3 permissions to escalate pr
../aws-post-exploitation/aws-s3-post-exploitation/README.md
{{#endref}}
+### S3 Express and S3 Access Grants credential brokers
+
+Directory buckets use `s3express:CreateSession` to vend short-lived credentials scoped to a bucket. S3 Access Grants uses `s3:GetDataAccess` to vend STS credentials scoped to a matching grant.[[24]](#references)[[25]](#references)
+
+```bash
+# Directory bucket session. The bucket name includes its Zone ID.
+aws s3api create-session \
+ --bucket ----x-s3 \
+ --session-mode ReadOnly
+
+# Access Grants session for one object. The account ID selects the Access
+# Grants instance, and the caller must be a grantee for the requested target.
+aws s3control get-data-access \
+ --account-id \
+ --target 's3:///' \
+ --target-type Object \
+ --permission READ \
+ --privilege Minimal \
+ --duration-seconds 900
+```
+
+The responses contain access key IDs, secret access keys, and session tokens. Do not print or persist them in normal enumeration output. Use an isolated shell and confirm the assumed identity and accessible scope before reading only authorized canary data.
+
+{% hint style="danger" %}
+Both brokers were validated end to end. `CreateSession` returned credentials only to the directory-bucket owner and denied three external accounts. For Access Grants, an explicitly granted role received STS credentials and read the exact canary object, while three external callers were denied. Every disposable bucket, object, grant, location, and role was deleted; a pre-existing Access Grants instance was not modified. Treat these permissions as **high** data-access capabilities for reachable resources, not as cross-account vulnerabilities.
+{% endhint %}
+
+If listing is denied, directory-bucket names occur in zonal S3 endpoints, application configuration, access logs, IaC state, and CloudTrail copies. Access Grants account IDs and targets occur in application profiles, EMR/DataZone configuration, role policies, audit events, and local SDK/CLI configuration. The broker calls do not require their corresponding list operations.
+
### Persistence
{{#ref}}
@@ -311,6 +340,33 @@ aws athena get-prepared-statement --statement-name --work-group
aws athena start-query-execution --query-string
```
+### Tested query-history and result disclosure
+
+`athena:GetQueryExecution` returns the complete SQL statement for a known execution ID, plus its workgroup, result location, encryption settings, statistics, and status.[[22]](#references) SQL history can contain customer identifiers, literal credentials/tokens, sensitive predicates, table names, and inline data.
+
+```bash
+aws athena get-query-execution --query-execution-id \
+ --query 'QueryExecution.{Query:Query,Database:QueryExecutionContext.Database,Result:ResultConfiguration,Status:Status}'
+```
+
+{% hint style="danger" %}
+This was validated with an STS session containing only `athena:GetQueryExecution`. An administrator executed a disposable `SELECT` containing a random sentinel as a SQL literal; the exact-action session recovered that sentinel from `QueryExecution.Query`. The result bucket and reader role were deleted. Treat this action as **high** for query-history disclosure.
+{% endhint %}
+
+`athena:GetQueryResults` has an important dependency: it returns rows for a completed execution, but AWS also checks access to the S3 result object.[[23]](#references)
+
+```bash
+# Tested minimum for an SSE-S3 result object; scope GetObject to the result prefix.
+aws athena get-query-results --query-execution-id
+# IAM: athena:GetQueryResults + s3:GetObject on the result object
+```
+
+{% hint style="warning" %}
+The exact `athena:GetQueryResults`-only session was denied with an error stating it lacked access to the S3 result location. A second session containing exactly `athena:GetQueryResults` and `s3:GetObject` recovered the sentinel row. Do **not** promote `athena:GetQueryResults` alone. SSE-KMS results can additionally require `kms:Decrypt`; direct `s3:GetObject` access can retrieve the result file even when Athena denies `GetQueryResults`.
+{% endhint %}
+
+`ListQueryExecutions` is only a discovery convenience. Query IDs also appear in console URLs, CloudTrail, SDK/CLI output, application logs, orchestration state, notebooks, shell history, and CI artifacts. Without AWS permissions, local Athena result downloads, cached notebook output, query text in repositories, and exported CSV files remain useful fallbacks.
+
## References
- [1] [CloudSecDocs CLI – S3 commands](https://cloudsecdocs.com/aws/defensive/tooling/cli/#s3)
@@ -334,5 +390,9 @@ aws athena start-query-execution --query-string
- [19] [Exploiting HTTP Parsers Inconsistencies](https://blog.bugport.net/exploiting-http-parsers-inconsistencies)
- [20] [Supported encryption algorithms – Amazon S3 Encryption Client](https://docs.aws.amazon.com/amazon-s3-encryption-client/latest/developerguide/encryption-algorithms.html)
- [21] [get-query-results – AWS CLI Command Reference](https://docs.aws.amazon.com/cli/latest/reference/athena/get-query-results.html)
+- [22] [GetQueryExecution API](https://docs.aws.amazon.com/athena/latest/APIReference/API_GetQueryExecution.html)
+- [23] [GetQueryResults API](https://docs.aws.amazon.com/athena/latest/APIReference/API_GetQueryResults.html)
+- [24] [CreateSession API](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateSession.html)
+- [25] [GetDataAccess CLI reference](https://docs.aws.amazon.com/cli/latest/reference/s3control/get-data-access.html)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-s3-tables-and-vectors-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-s3-tables-and-vectors-enum.md
new file mode 100644
index 0000000000..61dd863517
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-s3-tables-and-vectors-enum.md
@@ -0,0 +1,51 @@
+# AWS - S3 Tables and S3 Vectors Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## S3 Tables
+
+Amazon S3 Tables provides storage specialized for tabular data such as Apache Iceberg tables. Resources include table buckets, namespaces, and tables.[[1]](#references)
+
+```bash
+aws s3tables list-table-buckets
+aws s3tables get-table-bucket --table-bucket-arn
+aws s3tables get-table-bucket-policy --table-bucket-arn
+aws s3tables list-namespaces --table-bucket-arn
+aws s3tables list-tables --table-bucket-arn
+aws s3tables get-table \
+ --table-bucket-arn --namespace --name
+```
+
+## S3 Vectors
+
+S3 Vectors stores vector data in vector buckets and indexes for similarity search. Vector-bucket policies can grant cross-account access.[[2]](#references)
+
+```bash
+aws s3vectors list-vector-buckets
+aws s3vectors get-vector-bucket --vector-bucket-name
+aws s3vectors get-vector-bucket-policy --vector-bucket-name
+aws s3vectors list-indexes --vector-bucket-name
+aws s3vectors get-index \
+ --vector-bucket-name --index-name
+```
+
+If listing is denied, recover bucket, namespace, table, or index identifiers from analytics catalogs, query-engine configuration, model/RAG configuration, IaC, application logs, CloudTrail copies, deployment output, or console URLs, then query known identifiers directly.
+
+## Post exploitation
+
+The tested policy-validation paths are `s3tables:PutTableBucketPolicy`, `s3tables:PutTablePolicy`, and `s3vectors:PutVectorBucketPolicy` on owned resources. They can confirm candidate external IAM principals but are expected validation behavior—not access to external tables, vectors, or accounts. Each call changes policy state and must remain manual.
+
+{{#ref}}
+../aws-post-exploitation/aws-iam-post-exploitation/aws-resource-policy-principal-validation.md
+{{#endref}}
+
+## References
+
+- [1] [Amazon S3 Tables API operations](https://docs.aws.amazon.com/AmazonS3/latest/API/API_Operations_Amazon_S3_Tables.html)
+- [2] [Managing S3 Vectors vector-bucket policies](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-vectors-bucket-policy.html)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-sagemaker-enum/README.md b/src/pentesting-cloud/aws-security/aws-services/aws-sagemaker-enum/README.md
index f39f915dab..d4e2887ea8 100644
--- a/src/pentesting-cloud/aws-security/aws-services/aws-sagemaker-enum/README.md
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-sagemaker-enum/README.md
@@ -157,6 +157,22 @@ Focus areas:[[21]](#references)[[22]](#references)[[23]](#references)
- Multi-model endpoints using an S3 model prefix (`ModelDataUrl`) and alternate `S3DataSource` or `ModelPackage` sources; check for cross-account model-package sharing.[[21]](#references)[[24]](#references)[[25]](#references)
- Network configs and security groups attached to endpoints.[[22]](#references)[[23]](#references)
+### `sagemaker:DescribeModel` — tested inference-environment secret disclosure
+
+In addition to image and model-data locations, `DescribeModel` returns each inference container's `Environment` map. Plaintext tokens, credentials, internal endpoints, or model configuration placed there are returned to the caller.[[21]](#references)
+
+```bash
+# ListModels is optional when the model name is already known.
+aws sagemaker describe-model --model-name --region \
+ --query '{Role:ExecutionRoleArn,Primary:PrimaryContainer,Containers:Containers,Vpc:VpcConfig}'
+```
+
+{% hint style="danger" %}
+This was validated through an STS session policy containing only `sagemaker:DescribeModel`. A disposable model referenced an AWS inference image and stored a unique random sentinel in `PrimaryContainer.Environment`; no endpoint or compute was created. The response returned the exact sentinel, then the model and unused execution role were deleted. Treat the action as **high** for inference configuration and plaintext environment disclosure, not as automatic access to the execution role.
+{% endhint %}
+
+The action accepts a known model name directly. When `ListModels` is denied, names can come from endpoint configurations, pipelines, Model Registry references, IaC, CI/CD output, CloudTrail, logs, or predictable deployment naming. Reading a `ModelDataUrl` only locates an S3 object; downloading it still requires independent S3/KMS authorization.
+
## Feature Store, Data Wrangler & Clarify
```bash
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-security-and-detection-services/aws-cloudwatch-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-security-and-detection-services/aws-cloudwatch-enum.md
index b26832feae..3ac8e3b34b 100644
--- a/src/pentesting-cloud/aws-security/aws-services/aws-security-and-detection-services/aws-cloudwatch-enum.md
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-security-and-detection-services/aws-cloudwatch-enum.md
@@ -146,6 +146,26 @@ aws logs filter-log-events \
**Potential Impact:** Disclosure of application data, credentials, tokens, PII, and security/audit events retained in CloudWatch Logs.
+### `logs:GetLogRecord`, `logs:GetQueryResults` — tested alternate log-data paths
+
+CloudWatch Logs Insights returns an opaque `@ptr` for each result. `GetLogRecord` accepts that pointer and returns the complete referenced record, including fields not displayed by the original query.[[34]](#references) A pointer can therefore outlive the permission/session that ran the query and should be handled as sensitive short-lived material.
+
+```bash
+# @ptr may come from an authorized query, a saved artifact, CI output, or tooling.
+aws logs get-log-record --log-record-pointer ''
+
+# GetQueryResults does not start a query; it reads a known query ID.
+aws logs get-query-results --query-id
+```
+
+`logs:GetQueryResults` returns the current status and all rows for a known Logs Insights query ID.[[35]](#references) It does not require `logs:StartQuery` when another principal already ran the query or its ID was recovered elsewhere.
+
+{% hint style="danger" %}
+Both actions were validated independently with STS sessions containing only the tested action. A disposable log group held a random sentinel. An administrator ran one Insights query, then the `logs:GetLogRecord` session recovered the sentinel using only its `@ptr`, and the `logs:GetQueryResults` session recovered it using only the query ID. The log group and roles were deleted. Treat both actions as **high** data reads.
+{% endhint %}
+
+If log-group discovery is denied, predictable Lambda/API Gateway/CloudTrail names, application configuration, IaC, error messages, dashboards, local scripts, CI artifacts, and console URLs can reveal group names, query IDs, or pointers. Pointers and query IDs are prerequisites, not authorization bypasses: AWS still evaluates the corresponding read action. Results queries eventually expire, so a missing ID is not proof that the permission is harmless.
+
### CloudWatch Monitoring & Events
For services such as EC2, **basic monitoring** publishes metrics every **5 minutes**, while **detailed monitoring** publishes them every **1 minute**. Alarms evaluate metrics over their configured periods and can invoke actions such as SNS notifications, Lambda functions, EC2 actions, or Auto Scaling actions when alarm state changes.[[10]](#references)[[14]](#references)
@@ -482,6 +502,19 @@ aws cloudwatch untag-resource --resource-arn --tag-keys
**Potential Impact**: Disruption of tag-based access control policies.
+## Post-exploitation principal validation
+
+Two owned CloudWatch-family resources expose expected resource-policy validation signals:
+
+- `logs:PutDeliveryDestinationPolicy` on a CloudWatch Logs delivery destination.
+- `oam:PutSinkPolicy` on an Observability Access Manager sink.
+
+The success/error difference can confirm a candidate external IAM principal but does not access external logs, metrics, traces, or accounts. Both operations change policy state and must never be run by a read-only enumerator.
+
+{{#ref}}
+../../aws-post-exploitation/aws-iam-post-exploitation/aws-resource-policy-principal-validation.md
+{{#endref}}
+
## References
- [1] [CloudWatch - CloudSecDocs](https://cloudsecdocs.com/aws/services/logging/cloudwatch/#general-info)
@@ -517,5 +550,7 @@ aws cloudwatch untag-resource --resource-arn --tag-keys
- [31] [Actions, resources, and condition keys for Amazon CloudWatch - legacy URL](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazoncloudwatch.html)
- [32] [GetLogEvents - Amazon CloudWatch Logs](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_GetLogEvents.html)
- [33] [FilterLogEvents - Amazon CloudWatch Logs](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_FilterLogEvents.html)
+- [34] [GetLogRecord - Amazon CloudWatch Logs](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_GetLogRecord.html)
+- [35] [GetQueryResults - Amazon CloudWatch Logs](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_GetQueryResults.html)
{{#include ../../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-ses-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-ses-enum.md
index 1a055b98d7..903748dfbc 100644
--- a/src/pentesting-cloud/aws-security/aws-services/aws-ses-enum.md
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-ses-enum.md
@@ -138,6 +138,20 @@ Candidate addresses can come from public websites, certificate or domain-registr
Suppression entries are sensitive recipient data but are not reusable credentials and do not by themselves grant the ability to send email.
+#### `ses:GetEmailTemplate` — tested template-content disclosure
+
+SES v2 `GetEmailTemplate` returns the complete subject, HTML, and text bodies for a known template name.[[18]](#references)
+
+```bash
+aws sesv2 get-email-template --template-name --region
+```
+
+{% hint style="danger" %}
+This was validated with an STS session containing exactly `ses:GetEmailTemplate`. A disposable template placed a random sentinel in all content fields and the read recovered it. The template and role were deleted. Treat the action as **high** content access: internal templates can disclose unreleased communications, private links, operational instructions, branding used for convincing phishing, and accidentally embedded credentials. It does not read already-delivered mail or substitute per-recipient variables.
+{% endhint %}
+
+`ListEmailTemplates` is not required. Names often exist in application configuration, source code, deployment files, campaign databases, logs, CloudTrail copies, CI/CD output, or error messages. These sources and locally cached/rendered template files remain permissionless fallbacks. Repeat the direct call in likely SES Regions and distinguish a missing template from an access denial.
+
### Post Exploitation
{{#ref}}
@@ -163,5 +177,6 @@ Suppression entries are sensitive recipient data but are not reusable credential
- [15] [ListSuppressedDestinations API](https://docs.aws.amazon.com/ses/latest/APIReference-V2/API_ListSuppressedDestinations.html)
- [16] [GetSuppressedDestination API](https://docs.aws.amazon.com/ses/latest/APIReference-V2/API_GetSuppressedDestination.html)
- [17] [Amazon SES v2 service authorization](https://docs.aws.amazon.com/service-authorization/latest/reference/list_sesv2.html)
+- [18] [GetEmailTemplate API](https://docs.aws.amazon.com/ses/latest/APIReference-V2/API_GetEmailTemplate.html)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-transcribe-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-transcribe-enum.md
new file mode 100644
index 0000000000..152669edcc
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-transcribe-enum.md
@@ -0,0 +1,37 @@
+# AWS - Transcribe Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Basic information
+
+Amazon Transcribe batch jobs convert audio or video in S3 into a transcript. `GetTranscriptionJob` returns job settings, input locations, status, and—after completion—a transcript URI.[[1]](#references)[[2]](#references) Transcripts can contain meetings, calls, personal data, authentication phrases, or other sensitive speech.
+
+## Recover a completed transcript
+
+The read-only **`transcribe:GetTranscriptionJob`** action can disclose both metadata and transcript content when a job name is known:
+
+```bash
+aws transcribe get-transcription-job \
+ --transcription-job-name \
+ --query 'TranscriptionJob.{Status:TranscriptionJobStatus,Input:Media.MediaFileUri,Transcript:Transcript.TranscriptFileUri}'
+
+uri="$(aws transcribe get-transcription-job \
+ --transcription-job-name \
+ --query 'TranscriptionJob.Transcript.TranscriptFileUri' --output text)"
+curl --fail --silent --show-error "$uri"
+```
+
+When no customer output bucket was configured, Transcribe provides a temporary service-managed URL. The URL can be downloaded without signing another AWS request while it remains valid.[[2]](#references)
+
+{% hint style="danger" %}
+This was validated end to end. Polly generated disposable audio containing a random three-word phrase; Transcribe processed it, and an STS session containing exactly `transcribe:GetTranscriptionJob` returned the service-managed `TranscriptFileUri`. Downloading that URL without AWS credentials recovered the exact phrase. The job, input bucket, objects, and role were deleted. Treat this action as **high** sensitive-data access for reachable jobs.
+{% endhint %}
+
+Customer-managed output locations behave differently: reading the object normally requires `s3:GetObject` and may also require `kms:Decrypt`. The returned URI is temporary, so save authorized evidence promptly rather than treating it as a durable public object.
+
+If `ListTranscriptionJobs` is denied, job names frequently appear without additional AWS permissions in application databases, source code, queues, Step Functions input/output, logs, CloudTrail copies, infrastructure-as-code, support tickets, or predictable application-generated identifiers. The media URI returned by the job is also a useful lead, although accessing its object remains a separate authorization decision.
+
+## References
+
+- [1] [How Amazon Transcribe works with input and output data](https://docs.aws.amazon.com/transcribe/latest/dg/how-input.html)
+- [2] [GetTranscriptionJob API](https://docs.aws.amazon.com/transcribe/latest/APIReference/API_GetTranscriptionJob.html)
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-vpc-lattice-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-vpc-lattice-enum.md
new file mode 100644
index 0000000000..4a094cd27f
--- /dev/null
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-vpc-lattice-enum.md
@@ -0,0 +1,37 @@
+# AWS - VPC Lattice Enum
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Basic information
+
+Amazon VPC Lattice is an application-networking service for connecting and securing services and resources across VPCs and accounts. Important resources include service networks, services, resource configurations, target groups, listeners, rules, and associations.[[1]](#references)
+
+## Enumeration
+
+```bash
+aws vpc-lattice list-service-networks
+aws vpc-lattice list-services
+aws vpc-lattice list-resource-configurations
+aws vpc-lattice list-target-groups
+aws vpc-lattice list-service-network-service-associations
+aws vpc-lattice list-service-network-vpc-associations
+aws vpc-lattice get-auth-policy --resource-identifier
+aws vpc-lattice get-resource-policy --resource-arn
+```
+
+If list operations fail, names, IDs, and generated DNS names can be recovered from application configuration, service-discovery configuration, IaC, deployment output, CloudTrail copies, logs, Route 53 records, or console URLs. Use the corresponding `Get*` operations on known identifiers.
+
+## Post exploitation
+
+`vpc-lattice:PutAuthPolicy` on an owned service or service network can validate candidate external IAM principals. This is expected resource-policy validation, not invocation of an external service and not an AWS vulnerability. It modifies authorization policy state and must not be run by read-only tooling.
+
+{{#ref}}
+../aws-post-exploitation/aws-iam-post-exploitation/aws-resource-policy-principal-validation.md
+{{#endref}}
+
+## References
+
+- [1] [What is Amazon VPC Lattice?](https://docs.aws.amazon.com/vpc-lattice/latest/ug/what-is-vpc-lattice.html)
+- [2] [`PutAuthPolicy`](https://docs.aws.amazon.com/vpc-lattice/latest/APIReference/API_PutAuthPolicy.html)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-workspaces-enum.md b/src/pentesting-cloud/aws-security/aws-services/aws-workspaces-enum.md
index 6258acf25c..727bbad859 100644
--- a/src/pentesting-cloud/aws-security/aws-services/aws-workspaces-enum.md
+++ b/src/pentesting-cloud/aws-security/aws-services/aws-workspaces-enum.md
@@ -208,17 +208,80 @@ Google Drive and OneDrive connectors synchronize through the user's external acc
### Streaming-URL boundary
-`appstream:CreateStreamingURL` creates a temporary URL for a specified stack, fleet, and `UserId`, with validity from 1 to 604800 seconds. This can represent session access and may select the S3 home-folder prefix derived from that user ID, but AWS classifies it as a Write operation.[[22]](#references)[[23]](#references)
+`appstream:CreateStreamingURL` creates a temporary URL for a specified stack, fleet, and `UserId`, with validity from 1 to 604800 seconds. AWS classifies the API as a Write operation.[[22]](#references)[[23]](#references) The URL is a bearer credential for the requested streaming session: whoever redeems it can interact with the applications, network access, and storage connectors available to that session.
{% hint style="danger" %}
-The validation account had no stack or fleet, and this read-only pass did not call `CreateStreamingURL`. Therefore it remains an **unvalidated candidate**, not a tested high/critical technique. Do not promote it until a real authorized lab proves which existing-user data becomes reachable and the URL/session is fully cleaned up.
+**Tested sensitive-data access:** an IAM identity with only `appstream:CreateStreamingURL` selected an API-authenticated victim `UserId`, redeemed the URL, and opened that user's pre-seeded S3 Home Folder file inside streamed Notepad++. The same identity was denied `DescribeStacks`. Rate this **high**, not critical: it can expose the selected user's application session and data, but this test did not cross an AWS IAM privilege boundary.
{% endhint %}
+#### Preconditions
+
+This is not a resource-independent session primitive. The attacker needs the names of an existing associated stack and fleet, the fleet must be usable, and the selected session must expose something valuable. For the S3 Home Folder path specifically:
+
+* the stack has `ConnectorType=HOMEFOLDERS`;
+* the victim identifier is known or guessable; and
+* data already exists below the prefix derived from that exact identifier.
+
+The tested identity did **not** need `DescribeStacks`, `DescribeFleets`, `DescribeSessions`, S3 permissions, or an AppStream user-pool user. Stack/fleet names and the victim identifier can instead come from logs, deployment files, tickets, browser history, naming conventions, CloudTrail, or another compromised principal. The stack's authentication model matters: this test used the API-created-session `user/custom/` layout and does not prove that inventing a SAML `NameID` bypasses the external IdP.
+
+#### Tested attack
+
+With known resource names and victim identifier:
+
+```bash
+aws appstream create-streaming-url \
+ --stack-name \
+ --fleet-name \
+ --user-id '' \
+ --application-id '' \
+ --validity 900 \
+ --region
+```
+
+Open the returned `StreamingURL` before it expires. In a Home Folder-enabled stack, browse the mapped **Home Folder** from the streamed application. The API does not return the S3 object itself; the impact occurs because AppStream maps the storage prefix for the caller-supplied `UserId` into the resulting session.
+
+The smallest policy used in the validation was:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [{
+ "Effect": "Allow",
+ "Action": "appstream:CreateStreamingURL",
+ "Resource": "*"
+ }]
+}
+```
+
+In the isolated `eu-west-1` test, the lab created a HOMEFOLDERS stack and one-instance on-demand fleet from the AWS sample image. It used a random synthetic victim identifier and placed a unique text sentinel at:
+
+```text
+s3://appstream2-36fb080bb8-eu-west-1--/user/custom//
+```
+
+The constrained identity was first denied `DescribeStacks`, then successfully called `CreateStreamingURL`. Redeeming that URL produced an `ACTIVE` victim session. The synthetic file appeared under **Home Folder**, and opening it in streamed Notepad++ returned the exact sentinel. This proves both URL redemption and data access; merely receiving a URL would not have been sufficient evidence.
+
+After validation, the session was expired and the fleet stopped. The fleet, stack, IAM user/access key/policy, AppStream service roles, S3 objects and service-installed bucket policy/bucket, security group, route table, subnet, internet gateway, and VPC were deleted. A separate tag/prefix/service audit returned no lab resources. AppStream places an explicit `s3:DeleteBucket` deny in its Home Folder bucket policy, so lab cleanup must remove that policy before deleting the bucket.
+
+#### Permissionless and read-only fallbacks
+
+If `CreateStreamingURL` is denied, the earlier enumeration paths still help scope the environment without changing it. If AppStream enumeration is also denied, search local deployment artifacts and CloudTrail for stack/fleet/user values. Independent S3 access is an even simpler route to the same Home Folder data:
+
+```bash
+printf '%s' '' | shasum -a 256
+aws s3api list-objects-v2 --bucket \
+ --prefix user/custom//
+aws s3api get-object --bucket \
+ --key user/custom//