AWS SSO全新PKCE认证带来安全希望(大部分情况下)

本文深入分析了AWS SSO新推出的PKCE认证机制如何有效防御设备代码钓鱼攻击,包含详细的技术实现原理、Python代码示例、安全机制对比,以及实际部署建议,为云安全从业者提供完整的技术参考。

AWS SSO全新PKCE认证带来安全希望(大部分情况下)

设备代码钓鱼简史

  • Sebastian Mora发布了博客文章并推出了"awsssome_phish"攻击工具
  • Chaim Sanders撰文探讨AWS生态中设备代码钓鱼的风险
  • Matthew Garrett指出设备代码认证绕过了近年实施的多种高级安全机制
  • Rami McCarthy发布了建议指南, outlining AWS应采取的措施
  • Chris Norman推出了可防御设备代码钓鱼的开源浏览器扩展

虽然未见实际攻击报告,但至少两个红队反馈设备代码钓鱼极其有效。

re:Invent 2024——新希望

AWS在re:Invent前几天宣布推出"基于PKCE的SSO授权",该功能现已在AWS CLI 2.22.0及以上版本中默认启用。PKCE本质上是标准OAuth 2.0授权码流的实现。

基于PKCE的新认证流程UI

以下是概念性流程序列图:

该流程与设备代码认证的根本区别在于:成功认证后,AWS将用户重定向到localhost。客户端应用程序通过启动临时Web服务器获取授权码。关键意义在于:攻击者创建恶意认证链接时无法获取授权令牌来冒充受害者。

技术实现细节

AWS CLI的实现(特别是SSOTokenFetcherAuth类)展示了具体机制。以下是简化的Python实现示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
"""注意:需要最新boto3版本。请替换下面的SSO开始URL"""
SSO_START_URL='https://d-1234.awsapps.com/start'

import boto3
import jwt
import json
import urllib.parse
import secrets
import base64
import hashlib

def generate_code_verifier_and_challenge():
    # 生成密码学随机code_verifier
    code_verifier = base64.urlsafe_b64encode(secrets.token_bytes(32)).rstrip(b'=').decode('utf-8')
    
    # 从code_verifier计算code_challenge
    digest = hashlib.sha256(code_verifier.encode('utf-8')).digest()
    code_challenge = base64.urlsafe_b64encode(digest).rstrip(b'=').decode('utf-8')
    
    return code_verifier, code_challenge

sso_oidc = client = boto3.client('sso-oidc')
redirect_uri = "http://127.0.0.1"

response = client.register_client(
    clientName='pkce-demo',
    clientType='PUBLIC',
    scopes=["sso:account:access"],
    redirectUris=[
       redirect_uri
    ],

    grantTypes=["authorization_code", "refresh_token"],
)

client_id = response['clientId']
client_secret = response['clientSecret']
code_verifier, code_challenge = generate_code_verifier_and_challenge()

url = "https://oidc.us-east-1.amazonaws.com/authorize?response_type=code"
url += f"&client_id={client_id}"
url += f"&redirect_uri={urllib.parse.quote(redirect_uri)}"
url += "&state=dontcare"
url += "&code_challenge_method=S256"
url += "&scopes=sso%3Aaccount%3Aaccess"
url += f"&code_challenge={code_challenge}"

# 不验证签名解码JWT
claims = jwt.decode(client_secret, options={"verify_signature": False})

# 交互式读取令牌
print("请在浏览器中打开此URL:") 
print(url)
print()
print("当被重定向到localhost时,粘贴OAuth代码:")
code = input("OAuth代码: ")

response = client.create_token(
    grantType='authorization_code',
    clientId=client_id,
    clientSecret=client_secret,
    redirectUri=redirect_uri,
    codeVerifier=code_verifier,
    code=code
)
access_token = response['accessToken']

print("成功获取AWS SSO访问令牌。")
print("可用AWS账户:")
sso_client = boto3.client('sso')
response = sso_client.list_accounts(accessToken=access_token)
for account in response.get('accountList', []):
    print(f" - {account['accountName']} ({account['accountId']})")

示例输出:

1
2
3
4
5
6
7
8
9
请在浏览器中打开此URL:
https://oidc.us-east-1.amazonaws.com/authorize?response_type=code&client_id=icBsllQ8y8kJWfyMjKH3cnVzLWVhc3QtMQ&redirect_uri=http%3A//127.0.0.1&state=dontcare&code_challenge_method=S256&scopes=sso%3Aaccount%3Aaccess&code_challenge=wJYlfWmU3ejXGVbUbiXhahQHUaexSrlcLSQahygGCkk

当被重定向到localhost时,粘贴OAuth代码:
OAuth代码: eyJr...TB2d5pEmNPNJ6GMNypXkAr
成功获取AWS SSO访问令牌。
可用AWS账户:
- Sandbox (12345678901)
- Honeypots (1111111111)

攻击者能否使用恶意重定向URL窃取授权令牌?

OAuth实现中最常见的漏洞是允许攻击者构造重定向到攻击者控制域的恶意认证URL。AWS通过限制重定向URL为localhost来缓解此风险,确保只有AWS CLI启动的临时Web服务器能接收授权码。

这真的不能用于钓鱼攻击吗?

绝对不行——至少设计上如此。唯一潜在风险是AWS实现中存在漏洞,例如攻击者能绕过重定向URL白名单。

那么…我们安全了吗?

不幸的是,虽然基于PKCE的认证是正确的方向,但设备代码认证仍然可用且无法禁用。这个新版本并未完全消除它本应缓解的攻击向量。

建议措施

  • 将AWS CLI升级到最新版本(2.22.0+)
  • 鼓励组织内全员转向PKCE流程
  • 使用CloudTrail检测旧设备代码流的使用
  • 在网络层面阻止device.sso..amazonaws.com
  • 向AWS TAM反馈设备代码钓鱼问题
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计