阿里云AssumeRole权限滥用导致的危害
前言:阿里云AssumeRole滥用导致的危害利用笔记
参考文章:https://www.cnblogs.com/LittleHann/p/17894438.html
参考文章:https://help.aliyun.com/zh/oss/developer-reference/use-temporary-access-credentials-provided-by-sts-to-access-oss
关于AssumeRole权限
在云计算环境中,"AssumeRole" 是一个与身份和访问管理(IAM)相关的功能。它允许一个用户或服务以编程方式临时获取另一个角色的权限,这通常用于跨账户访问资源或执行特定任务而不需要长期提供访问凭证。
什么时候会用到AssumeRole权限
-
跨RAM用户访问各自账号的资源,就比如B子用户的数据需要传输到A子用户的存储桶中,但是默认B子用户没有A子用户的OSS存储桶权限,那么B子用户就可以通过AssumeRole来进行模拟A子用户的OSS存储桶权限来进行上传,既保证了权限的最小化又实现了数据传输。
-
假设你使用Jenkins或GitHub Actions来构建和部署应用程序,需要在构建过程中获取权限来推送Docker镜像到其他地方,这里的话也可以用到AssumeRole权限。
-
在实际情况下最常见的就是某些api上传接口返回一个sts token的情况,这个实际上就是对方服务器内部申请的sts token,这个token就是只能上传指定的oss。
环境模拟
创建RAM用户
登录RAM控制台,在左侧导航栏,选择身份管理>用户,单击创建用户,我这边创建一个assumetest的用户
注:需勾选OpenAPI调用访问
为RAM用户授予请求AssumeRole的权限
单击已创建RAM用户右侧对应的添加权限,在新增授权页面,给上面创建的assumetest用户选择AliyunSTSAssumeRoleAccess系统策略。
创建RAM角色
在左侧导航栏,选择身份管理>角色,单击创建角色,选择可信实体类型为阿里云账号,在创建角色对话框,角色名称填写为ossram,选择信任的云账号为当前云账号。
在角色页面,搜索框输入角色名称ossram,然后单击ossram。
单击ARN右侧的复制,保存角色的ARN,这是我的arn信息acs:ram::1323936485440166:role/ossram
,如下图所示
为RAM角色授予上传文件的权限
为RAM角色附加一个或多个权限策略,明确RAM角色在被扮演时所能拥有的OSS资源访问权限。
当前我希望RAM用户在扮演该角色后只能向vul-collection-test的OSS存储桶上传文件,则需要为角色添加写入权限的策略。
在左侧导航栏,选择权限管理>权限策略,在权限策略页面,单击创建权限策略。
在创建权限策略页面,单击脚本编辑,然后在策略文档输入框中赋予角色上传文件到vul-collection-test(这个是我自己的oss存储桶的名称)的权限,具体配置示例如下所示
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": [
"oss:PutObject"
],
"Resource": [
"acs:oss:*:*:vul-collection-test/*"
]
}
]
}
为RAM角色ossram授予自定义权限策略,在左侧导航栏,选择身份管理 > 角色。
在角色页面,找到目标RAM角色ossram,单击RAM角色ossram右侧的新增授权,选择已创建的自定义权限策略oss-policy
使用RAM用户扮演RAM角色获取临时访问凭证
为角色授予上传文件的权限后,RAM用户需要通过扮演角色来获取临时访问凭证。临时访问凭证包括安全令牌(SecurityToken)、临时访问密钥(AccessKeyId和AccessKeySecret)以及过期时间(Expiration)。
我上面创建的ram用户信息如下所示
用户信息: assumetest@1323936485440166.onaliyun.com
aksk信息:LTAI5tFc5Th9zrDPCxEssykS / Lj8y94TWwYhyFXvJdG73JVrhtyxjcP
arn信息:acs:ram::1323936485440166:role/ossram
自定义ram角色:ossram
相关maven依赖,如下所示
<!-- https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-core -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.6.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.aliyun.oss/aliyun-sdk-oss -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.18.1</version>
</dependency>
获取临时访问凭证代码,将上面的aksk和arn以及ram角色信息填充进去,如下所示
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
public class TestMain {
public static void main(String[] args) {
// STS服务接入点,例如sts.cn-hangzhou.aliyuncs.com。您可以通过公网或者VPC接入STS服务。
String endpoint = "sts.cn-hangzhou.aliyuncs.com";
// 从环境变量中获取步骤1生成的RAM用户的访问密钥(AccessKey ID和AccessKey Secret)。
String accessKeyId = "LTAI5tFc5Th9zrDPCxEssykS";
String accessKeySecret = "Lj8y94TWwYhyFXvJdG73JVrhtyxjcP";
// 从环境变量中获取步骤3生成的RAM角色的RamRoleArn。
String roleArn = "acs:ram::1323936485440166:role/ossram";
// 自定义角色会话名称,用来区分不同的令牌,例如可填写为SessionTest。
String roleSessionName = "ossram";
// 临时访问凭证将获得角色拥有的所有权限。
String policy = null;
// 临时访问凭证的有效时间,单位为秒。最小值为900,最大值以当前角色设定的最大会话时间为准。当前角色最大会话时间取值范围为3600秒~43200秒,默认值为3600秒。
// 在上传大文件或者其他较耗时的使用场景中,建议合理设置临时访问凭证的有效时间,确保在完成目标任务前无需反复调用STS服务以获取临时访问凭证。
Long durationSeconds = 3600L;
try {
// 发起STS请求所在的地域。建议保留默认值,默认值为空字符串("")。
String regionId = "";
// 添加endpoint。适用于Java SDK 3.12.0及以上版本。
DefaultProfile.addEndpoint(regionId, "Sts", endpoint);
// 添加endpoint。适用于Java SDK 3.12.0以下版本。
// DefaultProfile.addEndpoint("",regionId, "Sts", endpoint);
// 构造default profile。
IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
// 构造client。
DefaultAcsClient client = new DefaultAcsClient(profile);
final AssumeRoleRequest request = new AssumeRoleRequest();
// 适用于Java SDK 3.12.0及以上版本。
request.setSysMethod(MethodType.POST);
// 适用于Java SDK 3.12.0以下版本。
// request.setMethod(MethodType.POST);
request.setRoleArn(roleArn);
request.setRoleSessionName(roleSessionName);
request.setPolicy(policy);
request.setDurationSeconds(durationSeconds);
final AssumeRoleResponse response = client.getAcsResponse(request);
System.out.println("Expiration: " + response.getCredentials().getExpiration());
System.out.println("Access Key Id: " + response.getCredentials().getAccessKeyId());
System.out.println("Access Key Secret: " + response.getCredentials().getAccessKeySecret());
System.out.println("Security Token: " + response.getCredentials().getSecurityToken());
System.out.println("RequestId: " + response.getRequestId());
} catch (ClientException e) {
System.out.println("Failed:");
System.out.println("Error code: " + e.getErrCode());
System.out.println("Error message: " + e.getErrMsg());
System.out.println("RequestId: " + e.getRequestId());
}
}
}
成功获取相关的sts token,如下图所示
使用临时访问凭证上传文件至OSS
我这里测试的存储桶为vul-collection-test
,通过sdk编写对应的上传oss来进行测试
运行了上面的代码之后来到vul-collection-test
存储桶进行查看,可以看到成功上传了对应的文件
AssumeRole滥用情况利用
这边再创建一个ECS相关权限的RAM角色,如下图所示
如果我们拿到了类似下面这样的arn信息,我们该如何进行利用呢?
arn信息:acs:ram::1323936485440166:role/ecsram
自定义ram角色:ecsram