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类似,此方法也使用密钥管理服务生成您的数据加密密钥。但是,这次是客户端调用KMS而不是S3。然后在客户端进行加密,然后将加密数据发送到S3进行存储。

  • 加密:

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

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

  • 两个密钥都被发送回来

  • 然后客户端使用明文DEK加密数据,并将加密数据发送到S3,同时发送加密数据 + 加密DEK(保存为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

双栈

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

双栈端点使用以下语法:

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

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

提权

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

AWS - S3 Privesc

未经身份验证的访问

AWS - S3 Unauthenticated Enum

S3后渗透

AWS - S3 Post Exploitation

持久性

AWS - S3 Persistence

其他S3漏洞

S3 HTTP缓存投毒问题

根据这项研究 可以缓存任意存储桶的响应,就好像它属于另一个存储桶一样。这可能被滥用来更改例如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用户需要特定的权限才能执行查询。

枚举

# 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