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 权限以提升权限

AWS - S3 Privesc

Unauthenticated Access

AWS - S3 Unauthenticated Enum

S3 Post Exploitation

AWS - S3 Post Exploitation

Persistence

AWS - S3 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