# AWS - S3, Athena & Glacier 列挙

{{#include ../../../banners/hacktricks-training.md}}

## S3

Amazon S3 は **大量のデータを保存** できるサービスです。

Amazon S3 は静止状態のデータの**保護**を実現するための複数のオプションを提供しています。オプションには **Permission**（Policy）、**Encryption**（クライアント側およびサーバー側）、**Bucket Versioning**、および **MFA** **based delete** が含まれます。**ユーザーが有効化できる**これらのいずれかのオプションによりデータ保護を実現できます。**Data replication** は AWS の内部機能で、**S3 が各オブジェクトをすべての Availability Zones に自動的に複製する**ため、組織がそれを有効にする必要はありません。

リソースベースの権限を使用すると、バケットのサブディレクトリに対して個別に権限を定義できます。

### Bucket Versioning and MFA based delete

Bucket Versioning が有効な場合、ファイルを変更しようとする操作は新しいバージョンを生成し、以前の内容も保持します。そのため、内容は上書きされません。

さらに、MFA based delete は S3 バケット内のファイルのバージョンが削除されるのを防ぎ、Bucket Versioning が無効化されるのも防ぐため、攻撃者はこれらのファイルを変更できません。

### S3 Access logs

あるバケットに対して **S3 アクセスログを有効化**（デフォルトでは無効）し、ログを別のバケットに保存することで誰がバケットにアクセスしているかを把握できます（両方のバケットは同じリージョンである必要があります）。

### S3 Presigned URLs

バケット内の特定のファイルに通常**アクセスする**ために使用できる presigned URL を生成することが可能です。**presigned URL は次のようになります**：
```
https://<bucket-name>.s3.us-east-1.amazonaws.com/asd.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIAUUE8GZC4S5L3TY3P%2F20230227%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230227T142551Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Security-Token=IQoJb3JpZ2luX2VjELf%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaCXVzLWVhc3QtMSJHMEUCIBhQpdETJO3HKKDk2hjNIrPWwBE8gZaQccZFV3kCpPCWAiEAid3ueDtFFU%2FOQfUpvxYTGO%2BHoS4SWDMUrQAE0pIaB40qggMIYBAAGgwzMTgxNDIxMzg1NTMiDJLI5t7gr2EGxG1Y5CrfAioW0foHIQ074y4gvk0c%2B%2Fmqc7cNWb1njQslQkeePHkseJ3owzc%2FCwkgE0EuZTd4mw0aJciA2XIbJRCLPWTb%2FCBKPnIMJ5aBzIiA2ltsiUNQTTUxYmEgXZoJ6rFYgcodnmWW0Et4Xw59UlHnCDB2bLImxPprriyCzDDCD6nLyp3J8pFF1S8h3ZTJE7XguA8joMs4%2B2B1%2FeOZfuxXKyXPYSKQOOSbQiHUQc%2BFnOfwxleRL16prWk1t7TamvHR%2Bt3UgMn5QWzB3p8FgWwpJ6GjHLkYMJZ379tkimL1tJ7o%2BIod%2FMYrS7LDCifP9d%2FuYOhKWGhaakPuJKJh9fl%2B0vGl7kmApXigROxEWon6ms75laXebltsWwKcKuYca%2BUWu4jVJx%2BWUfI4ofoaGiCSaKALTqwu4QNBRT%2BMoK6h%2BQa7gN7JFGg322lkxRY53x27WMbUE4unn5EmI54T4dWt1%2Bg8ljDS%2BvKfBjqmAWRwuqyfwXa5YC3xxttOr3YVvR6%2BaXpzWtvNJQNnb6v0uI3%2BTtTexZkJpLQYqFcgZLQSxsXWSnf988qvASCIUhAzp2UnS1uqy7QjtD5T73zksYN2aesll7rvB80qIuujG6NOdHnRJ2M5%2FKXXNo1Yd15MtzPuSjRoSB9RSMon5jFu31OrQnA9eCUoawxbB0nHqwK8a43CKBZHhA8RoUAJW%2B48EuFsp3U%3D&X-Amz-Signature=3436e4139e84dbcf5e2e6086c0ebc92f4e1e9332b6fda24697bc339acbf2cdfa
```
presigned URL は **オブジェクトへアクセス権を持つ principal の資格情報を使って cli から作成できます**（使用しているアカウントにアクセス権がない場合、より短い presigned URL が作成されますが、役に立ちません）
```bash
aws s3 presign --region <bucket-region> 's3://<bucket-name>/<file-name>'
```
> [!NOTE]
> presigned URL を生成するのに必要な唯一の権限は付与される権限そのものであり、したがって前のコマンドではプリンシパルに必要なのは `s3:GetObject` のみです

また、**他の権限**を使って presigned URL を作成することも可能です:
```python
import boto3
url = boto3.client('s3').generate_presigned_url(
ClientMethod='put_object',
Params={'Bucket': 'BUCKET_NAME', 'Key': 'OBJECT_KEY'},
ExpiresIn=3600
)
```
### S3 暗号化メカニズム

**DEKはData Encryption Key（データ暗号化鍵）を意味し**、常に生成されデータの暗号化に使用される鍵です。

<details>

<summary><strong>Server-side encryption with S3 managed keys, SSE-S3</strong></summary>

このオプションはほとんど設定を必要とせず、使用される暗号化鍵の管理はすべてAWSが行います。あなたがやるべきことは**データをアップロードするだけで、S3がそれ以外の処理をすべて行います**。S3アカウント内の各バケットにはバケットキーが割り当てられます。

- 暗号化:
- Object Data + 生成されたプレーンテキストDEK --> 暗号化データ（S3内に保存）
- 生成されたプレーンテキストDEK + S3 Master Key --> 暗号化DEK（S3内に保存）およびプレーンテキストはメモリから削除
- 復号化:
- 暗号化DEK + S3 Master Key --> プレーンテキストDEK
- プレーンテキストDEK + 暗号化データ --> オブジェクトデータ

なお、この場合**鍵はAWSによって管理されます**（ローテーションは3年ごと）。自身のキーを使用する場合は、ローテーション、無効化、およびアクセス制御の適用が可能になります。

</details>

<details>

<summary><strong>Server-side encryption with KMS managed keys, SSE-KMS</strong></summary>

この方法ではS3がKMSを用いてデータ暗号化キーを生成できます。KMSにより鍵管理の柔軟性が大幅に向上します。たとえば、CMKを無効化、ローテーション、アクセス制御でき、AWS Cloud Trailを使って使用状況を監査できます。

- 暗号化:
- S3がKMSのCMKからデータキーを要求する
- KMSはCMKを使ってプレーンテキストDEKと暗号化DEKのペアを生成し、それらをS3に返す
- S3はプレーンテキストキーでデータを暗号化し、暗号化データと暗号化DEKを保存し、プレーンテキストキーをメモリから削除する
- 復号化:
- S3はオブジェクトの暗号化データキーを復号するようKMSに依頼する
- KMSはCMKでデータキーを復号しS3に返す
- S3はオブジェクトデータを復号する

</details>

<details>

<summary><strong>Server-side encryption with customer provided keys, SSE-C</strong></summary>

このオプションでは、AWS外で既に使用しているかもしれない自分のマスターキーを提供することができます。顧客提供キーはデータとともにS3に送信され、S3が代わりに暗号化を行います。

- 暗号化:
- ユーザーがオブジェクトデータ + Customer key をS3に送信する
- Customer keyがデータの暗号化に使われ、暗号化データが保存される
- Customer keyのソルト付きHMAC値も将来のキー検証のために保存される
- Customer keyはメモリから削除される
- 復号化:
- ユーザーがcustomer keyを送信する
- 保存されたHMAC値と照合してキーが検証される
- 顧客提供キーがデータの復号に使用される

</details>

<details>

<summary><strong>Client-side encryption with KMS, CSE-KMS</strong></summary>

SSE-KMSと同様に、KMSを使ってデータ暗号化キーを生成します。ただし今回はKMSはS3ではなくクライアントから呼び出されます。暗号化はクライアント側で行われ、その暗号化データがS3に送られて保存されます。

- 暗号化:
- クライアントがKMSにデータキーを要求する
- KMSはプレーンテキストDEKとCMKで暗号化されたDEKを返す
- 両方のキーがクライアントに返される
- クライアントはプレーンテキストDEKでデータを暗号化し、暗号化データと暗号化DEK（S3内の暗号化データのメタデータとして保存）をS3に送信する
- 復号化:
- 暗号化データと暗号化DEKがクライアントに送信される
- クライアントはCMKを使って暗号化DEKを復号するようKMSに依頼し、KMSはプレーンテキストDEKを返す
- クライアントはそのDEKで暗号化データを復号できる

</details>

<details>

<summary><strong>Client-side encryption with customer provided keys, CSE-C</strong></summary>

この仕組みでは、自分で用意したキーを使い、AWS-SDKクライアントでデータを暗号化してからS3に送信できます。

- 暗号化:
- クライアントがDEKを生成しプレーンテキストデータを暗号化する
- その後、自身のcustom CMKでDEKを暗号化する
- 暗号化データと暗号化DEKをS3に送信して保存する
- 復号化:
- S3が暗号化データとDEKを送信する
- クライアントはDEKを暗号化したCMKを既に持っているため、DEKを復号しプレーンテキストDEKでデータを復号する

</details>

### **列挙**

伝統的にAWS組織を侵害する主要な方法の一つは、公開アクセス可能なバケットを侵害することです。**こちらで見つけられます** [**public buckets enumerators in this page**](../aws-unauthenticated-enum-access/index.html#s3-buckets)**.**
```bash
# Get buckets ACLs
aws s3api get-bucket-acl --bucket <bucket-name>
aws s3api get-object-acl --bucket <bucket-name> --key flag

# Get policy
aws s3api get-bucket-policy --bucket <bucket-name>
aws s3api get-bucket-policy-status --bucket <bucket-name> #if it's public

# list S3 buckets associated with a profile
aws s3 ls
aws s3api list-buckets

# list content of bucket (no creds)
aws s3 ls s3://bucket-name --no-sign-request
aws s3 ls s3://bucket-name --recursive

# list content of bucket (with creds)
aws s3 ls s3://bucket-name
aws s3api list-objects-v2 --bucket <bucket-name>
aws s3api list-objects --bucket <bucket-name>
aws s3api list-object-versions --bucket <bucket-name>

# copy local folder to S3
aws s3 cp MyFolder s3://bucket-name --recursive

# delete
aws s3 rb s3://bucket-name –-force

# download a whole S3 bucket
aws s3 sync s3://<bucket>/ .

# move S3 bucket to different location
aws s3 sync s3://oldbucket s3://newbucket --source-region us-west-1

# list the sizes of an S3 bucket and its contents
aws s3api list-objects --bucket BUCKETNAME --output json --query "[sum(Contents[].Size), length(Contents[])]"

# Update Bucket policy
aws s3api put-bucket-policy --policy file:///root/policy.json --bucket <bucket-name>
##JSON policy example
{
"Id": "Policy1568185116930",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1568184932403",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::welcome",
"Principal": "*"
},
{
"Sid": "Stmt1568185007451",
"Action": [
"s3:GetObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::welcome/*",
"Principal": "*"
}
]
}

# Update bucket ACL
aws s3api get-bucket-acl --bucket <bucket-name> # Way 1 to get the ACL
aws s3api put-bucket-acl --bucket <bucket-name> --access-control-policy file://acl.json

aws s3api get-object-acl --bucket <bucket-name> --key flag #Way 2 to get the ACL
aws s3api put-object-acl --bucket <bucket-name> --key flag --access-control-policy file://objacl.json

##JSON ACL example
## Make sure to modify the Owner’s displayName and ID according to the Object ACL you retrieved.
{
"Owner": {
"DisplayName": "<DisplayName>",
"ID": "<ID>"
},
"Grants": [
{
"Grantee": {
"Type": "Group",
"URI": "http://acs.amazonaws.com/groups/global/AuthenticatedUsers"
},
"Permission": "FULL_CONTROL"
}
]
}
## An ACL should give you the permission WRITE_ACP to be able to put a new ACL
```
### dual-stack <a href="#dual-stack-endpoints-description" id="dual-stack-endpoints-description"></a>

virtual hosted-style または path-style のエンドポイント名を使用して、dual-stack エンドポイント経由で S3 バケットにアクセスできます。これらは IPv6 経由で S3 にアクセスする際に便利です。

Dual-stack エンドポイントは次の構文を使用します:

- `bucketname.s3.dualstack.aws-region.amazonaws.com`
- `s3.dualstack.aws-region.amazonaws.com/bucketname`

### Privesc

以下のページで **S3 の権限を悪用して権限昇格する方法** を確認できます:

{{#ref}}
../aws-privilege-escalation/aws-s3-privesc/README.md
{{#endref}}

### Unauthenticated Access

{{#ref}}
../aws-unauthenticated-enum-access/aws-s3-unauthenticated-enum/README.md
{{#endref}}

### S3 Post Exploitation

{{#ref}}
../aws-post-exploitation/aws-s3-post-exploitation/README.md
{{#endref}}

### Persistence

{{#ref}}
../aws-persistence/aws-s3-persistence/README.md
{{#endref}}

## Other S3 vulns

### S3 HTTP Cache Poisoning Issue <a href="#heading-s3-http-desync-cache-poisoning-issue" id="heading-s3-http-desync-cache-poisoning-issue"></a>

[**この調査によると**](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies#heading-s3-http-desync-cache-poisoning-issue)、任意のバケットのレスポンスを別のバケットのものとしてキャッシュできる場合がありました。これを悪用すると、例えば javascript ファイルのレスポンスを書き換えて、S3 を使って静的コードをホストしている任意のページを改竄することが可能になり得ます。

## Amazon Athena

Amazon Athena は、Amazon Simple Storage Service (Amazon **S3**) 内のデータを標準の **SQL** を使って直接 **分析する** のを容易にするインタラクティブなクエリサービスです。

監視対象の S3 バケットに含まれるコンテンツの形式に合わせて **リレーショナル DB テーブルを準備** する必要があります。すると、Amazon Athena はログから DB を構築できるようになり、クエリを実行できます。

Amazon Athena は **既に暗号化されている S3 データをクエリする機能** をサポートしており、設定によっては **Athena がクエリ結果を暗号化して S3 に保存することも可能** です。

**クエリ結果の暗号化は、基になるクエリ対象の S3 データの暗号化とは独立しています**。つまり、S3 データ自体が暗号化されていなくても、クエリ結果を暗号化することができます。注意点として、Amazon Athena は **次の S3 暗号化方式で暗号化されたデータ**、つまり **SSE-S3, SSE-KMS, and CSE-KMS** のみをサポートしています。

SSE-C と CSE-C はサポートされていません。加えて、Amazon Athena は **クエリを実行するリージョンと同じリージョンにある暗号化オブジェクトに対してのみクエリを実行する** ことにも注意が必要です。KMS を使って暗号化された S3 データをクエリする必要がある場合、Athena ユーザーにはそのクエリを実行するための特定の権限が要求されます。

### Enumeration
```bash
# Get catalogs
aws athena list-data-catalogs

# Get databases inside catalog
aws athena list-databases --catalog-name <catalog-name>
aws athena list-table-metadata --catalog-name <catalog-name> --database-name <db-name>

# Get query executions, queries and results
aws athena list-query-executions
aws athena get-query-execution --query-execution-id <id> # Get query and meta of results
aws athena get-query-results --query-execution-id <id> # This will rerun the query and get the results

# Get workgroups & Prepared statements
aws athena list-work-groups
aws athena list-prepared-statements --work-group <wg-name>
aws athena get-prepared-statement --statement-name <name> --work-group <wg-name>

# Run query
aws athena start-query-execution --query-string <query>
```
## 参考資料

- [https://cloudsecdocs.com/aws/defensive/tooling/cli/#s3](https://cloudsecdocs.com/aws/defensive/tooling/cli/#s3)
- [https://docs.aws.amazon.com/AmazonS3/latest/userguide/dual-stack-endpoints.html](https://docs.aws.amazon.com/AmazonS3/latest/userguide/dual-stack-endpoints.html)

{{#include ../../../banners/hacktricks-training.md}}
