AWS - S3, Athena & Glacier Enum

支持 HackTricks

S3

Amazon S3 是一个允许您 存储大量数据 的服务。

Amazon S3 提供多种选项来实现数据在静态时的 保护。这些选项包括 权限(策略)、加密(客户端和服务器端)、存储桶版本控制基于 MFA 的删除用户可以启用 这些选项中的任何一个来实现数据保护。数据复制 是 AWS 的一项内部功能,S3 会自动在所有可用区复制每个对象,因此组织在这种情况下无需启用它。

通过基于资源的权限,您可以单独为存储桶的子目录定义权限。

存储桶版本控制和基于 MFA 的删除

当启用存储桶版本控制时,任何试图更改文件的操作都会生成该文件的新版本,同时保留相同文件的先前内容。因此,它不会覆盖其内容。

此外,基于 MFA 的删除将防止 S3 存储桶中的文件版本被删除,也防止存储桶版本控制被禁用,因此攻击者将无法更改这些文件。

S3 访问日志

可以 启用 S3 访问日志(默认情况下是禁用的)到某个存储桶,并将日志保存在不同的存储桶中,以了解谁在访问该存储桶(两个存储桶必须在同一区域)。

S3 预签名 URL

可以生成一个预签名 URL,通常用于 访问存储桶中的指定文件。一个 预签名 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

一个预签名的 URL 可以使用具有访问对象权限的主体的凭证从 CLI 创建(如果您使用的帐户没有访问权限,将创建一个较短的预签名 URL,但它将无用)

aws s3 presign --region <bucket-region> 's3://<bucket-name>/<file-name>'

生成预签名 URL 所需的唯一权限是所给予的权限,因此对于之前的命令,主体所需的唯一权限是 s3:GetObject

还可以使用 其他权限 创建预签名 URL:

import boto3
url = boto3.client('s3').generate_presigned_url(
ClientMethod='put_object',
Params={'Bucket': 'BUCKET_NAME', 'Key': 'OBJECT_KEY'},
ExpiresIn=3600
)

S3 加密机制

DEK 代表数据加密密钥,是始终生成并用于加密数据的密钥。

使用 S3 管理密钥的服务器端加密,SSE-S3

此选项需要最少的配置,所有使用的加密密钥管理均由 AWS 管理。您只需 上传您的数据,S3 将处理所有其他方面。每个 S3 账户中的存储桶都分配一个存储桶密钥。

  • 加密:

  • 对象数据 + 创建的明文 DEK --> 加密数据(存储在 S3 中)

  • 创建的明文 DEK + S3 主密钥 --> 加密 DEK(存储在 S3 中),明文从内存中删除

  • 解密:

  • 加密 DEK + S3 主密钥 --> 明文 DEK

  • 明文 DEK + 加密数据 --> 对象数据

请注意,在这种情况下 密钥由 AWS 管理(每 3 年轮换一次)。如果您使用自己的密钥,您将能够轮换、禁用并应用访问控制。

使用 KMS 管理密钥的服务器端加密,SSE-KMS

此方法允许 S3 使用密钥管理服务生成您的数据加密密钥。KMS 为您提供了更大的密钥管理灵活性。例如,您可以禁用、轮换并对 CMK 应用访问控制,并使用 AWS Cloud Trail 监控其使用情况。

  • 加密:

  • S3 向 KMS CMK 请求数据密钥

  • KMS 使用 CMK 生成明文 DEK 和加密 DEK 对,并将其发送到 S3

  • S3 使用明文密钥加密数据,存储加密数据和加密密钥,并从内存中删除明文密钥

  • 解密:

  • S3 请求 KMS 解密对象的加密数据密钥

  • KMS 使用 CMK 解密数据密钥并将其发送回 S3

  • S3 解密对象数据

使用客户提供密钥的服务器端加密,SSE-C

此选项使您能够提供您可能已经在 AWS 之外使用的主密钥。您的客户提供的密钥将与您的数据一起发送到 S3,S3 将为您执行加密。

  • 加密:

  • 用户将对象数据 + 客户密钥发送到 S3

  • 客户密钥用于加密数据,且加密数据被存储

  • 还存储客户密钥的盐值 HMAC 值以供将来密钥验证

  • 客户密钥从内存中删除

  • 解密:

  • 用户发送客户密钥

  • 密钥与存储的 HMAC 值进行验证

  • 然后使用客户提供的密钥解密数据

使用 KMS 的客户端加密,CSE-KMS

与 SSE-KMS 类似,这也使用密钥管理服务生成您的数据加密密钥。然而,这次是通过客户端而不是 S3 调用 KMS。加密在客户端进行,随后将加密数据发送到 S3 存储。

  • 加密:

  • 客户端请求 KMS 的数据密钥

  • KMS 返回明文 DEK 和与 CMK 的加密 DEK

  • 两个密钥都被发送回

  • 客户端使用明文 DEK 加密数据,并将加密数据 + 加密 DEK(作为加密数据的元数据存储在 S3 中)发送到 S3

  • 解密:

  • 带有加密 DEK 的加密数据发送到客户端

  • 客户端请求 KMS 使用 CMK 解密加密密钥,KMS 返回明文 DEK

  • 客户端现在可以解密加密数据

使用客户提供密钥的客户端加密,CSE-C

使用此机制,您可以利用自己提供的密钥,并使用 AWS-SDK 客户端在将数据发送到 S3 存储之前对其进行加密。

  • 加密:

  • 客户端生成 DEK 并加密明文数据

  • 然后,使用自己的自定义 CMK 加密 DEK

  • 提交加密数据 + 加密 DEK 到 S3 进行存储

  • 解密:

  • S3 发送加密数据和 DEK

  • 由于客户端已经拥有用于加密 DEK 的 CMK,因此它解密 DEK,然后使用明文 DEK 解密数据

枚举

妥协 AWS 组织的传统主要方式之一是从妥协公开可访问的存储桶开始。 您可以在此页面找到 公共存储桶枚举工具.

# 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

您可以通过双栈端点使用虚拟托管样式或路径样式端点名称访问 S3 存储桶。这些对于通过 IPv6 访问 S3 很有用。

双栈端点使用以下语法:

  • bucketname.s3.dualstack.aws-region.amazonaws.com

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

Privesc

在以下页面中,您可以查看如何 滥用 S3 权限以提升权限

Unauthenticated Access

S3 Post Exploitation

Persistence

Other S3 vulns

S3 HTTP Cache Poisoning Issue

根据这项研究,可以将任意存储桶的响应缓存为属于不同的存储桶。这可能被滥用来更改例如 JavaScript 文件的响应,并利用 S3 存储静态代码来妥协任意页面。

Amazon Athena

Amazon Athena 是一种交互式查询服务,使您能够直接在 Amazon Simple Storage Service (Amazon S3) 中 分析数据使用 标准 SQL

您需要 准备一个关系数据库表,其格式与将出现在监控的 S3 存储桶中的内容相符。然后,Amazon Athena 将能够从日志中填充数据库,以便您可以查询它。

Amazon Athena 支持 查询已经加密的 S3 数据,如果配置为这样,Athena 还可以加密查询结果,然后将其存储在 S3 中

结果的加密与底层查询的 S3 数据无关,这意味着即使 S3 数据未加密,查询结果也可以加密。需要注意的几点是,Amazon Athena 仅支持使用 以下 S3 加密方法 加密 的数据,SSE-S3、SSE-KMS 和 CSE-KMS

SSE-C 和 CSE-E 不受支持。此外,重要的是要理解,Amazon Athena 仅会对 与查询本身在同一区域的加密对象 运行查询。如果您需要查询使用 KMS 加密的 S3 数据,则 Athena 用户需要特定权限以使其能够执行查询。

Enumeration

# 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>

参考文献

支持 HackTricks

Last updated