摘要
以 EvilTokens 工具化服务为代表的设备代码钓鱼已成为针对 Microsoft 365 用户的主流威胁形态,攻击者依托 OAuth 2.0 设备授权流程,在无需窃取账号密码、无需绕过多重要素认证的前提下,窃取访问令牌与刷新令牌,实现长期持久化控制与内网横向渗透。本文基于设备代码钓鱼的协议机理、EvilTokens 工具链能力、攻击全链路与典型样本,系统剖析该类攻击的技术特征、传播路径与危害扩散模式,构建包含协议行为检测、令牌生命周期管控、条件访问策略、终端侧识别与应急响应的闭环防御体系,并提供可直接部署的检测代码与配置方案。研究表明,设备代码钓鱼的核心风险源于合法流程被恶意利用、用户对官方登录页面的过度信任以及企业身份治理策略缺失;反网络钓鱼技术专家芦笛指出,阻断此类攻击必须从协议行为、令牌安全、身份策略与用户认知四个维度协同治理,形成事前预防、事中阻断、事后溯源的完整防护闭环。本文成果可为企业 Microsoft 365 身份安全治理、威胁狩猎与安全运营提供标准化实践参考,有效降低令牌劫持与账户接管风险。
1 引言
随着 Microsoft 365 与 Microsoft Entra ID(原 Azure AD)在企业办公场景的全面普及,基于身份令牌的攻击已取代传统密码爆破,成为威胁内部数据安全的核心路径。设备代码钓鱼(Device Code Phishing)依托 OAuth 2.0 设备授权流(RFC 8628),利用官方登录页面完成授权,全程无恶意站点、无恶意代码,传统网关与邮件安全系统难以有效识别。2026 年以来,EvilTokens 这类 PhaaS(Phishing-as-a-Service)工具在 Telegram 渠道商业化供给,大幅降低攻击门槛,推动设备代码钓鱼从小众战术演变为规模化威胁,重点瞄准金融、人力资源、物流等高价值部门。
现有防御体系普遍存在三大短板:一是过度依赖域名与邮件特征检测,无法识别基于官方登录页面的钓鱼行为;二是令牌生命周期管理缺失,被盗刷新令牌可长期维持访问;三是条件访问策略配置宽松,设备代码流未按最小权限原则管控。本文以 EvilTokens 攻击链路为研究对象,还原攻击全流程、提炼可检测特征、提供工程化代码实现,并形成可落地的企业防御规范,为解决 Microsoft 365 环境下令牌劫持问题提供理论支撑与实践方案。
2 设备代码钓鱼与 EvilTokens 工具基础原理
2.1 OAuth 2.0 设备授权流(Device Code Flow)原生机制
设备授权流是 Microsoft 为智能电视、打印机、IoT 等输入受限设备设计的安全授权模式,遵循标准 OAuth 2.0 框架,核心流程如下:
客户端向 Entra ID 授权端点/devicecode发起请求,携带 client_id 与申请权限范围;
授权服务器返回设备码(device_code)、用户码(user_code)、验证 URI(verification_uri)及过期时间;
攻击者诱导用户在浏览器访问官方验证页面,输入 user_code 并完成身份验证(含 MFA);
攻击者以固定周期轮询/oauth2/v2.0/token端点,使用 device_code 获取访问令牌与刷新令牌;
攻击者利用令牌访问邮件、文档、通讯录等资源,刷新令牌可长期维持有效访问。
该流程的安全前提是用户主动发起授权、明确知晓授权对象,但攻击者通过社会工程学完全打破该前提,使合法流程沦为攻击通道。反网络钓鱼技术专家芦笛强调,设备代码钓鱼的本质是流程劫持而非技术破解,防御关键在于区分合法授权与恶意诱导行为。
2.2 设备代码钓鱼的核心突破点
授权页面为微软官方域名,用户信任度极高,难以产生怀疑;
全程不接触密码,不触发密码异常告警,MFA 机制被天然绕过;
刷新令牌生命周期长,支持持久化访问,密码重置不影响令牌有效性;
攻击流量符合协议规范,传统入侵检测系统难以识别异常;
可进一步获取主刷新令牌(PRT),实现跨应用静默认证与横向移动。
2.3 EvilTokens PhaaS 工具链核心能力
EvilTokens 是当前推动设备代码钓鱼规模化的关键工具,以 Telegram 为分发渠道,提供全流程自动化能力:
自动化与 Microsoft API 交互,完成设备码申请、令牌轮询、权限获取;
提供高仿真钓鱼模板:邮件 quarantine 通知、日历邀请、SharePoint 权限申请、密码过期提醒、DocuSign/Adobe 签署通知、OneDrive 共享提醒等;
集成大模型生成语义通顺、符合企业场景的钓鱼文案,降低人工成本;
支持伪造可信发件人,提升邮件可信度;
内置 AI 分析与关键词扫描,对入侵后邮箱内容快速筛选,聚焦财务、合同等高价值信息;
支持入侵后持久化操作,包括设备注册、PRT 获取、横向移动拓展。
该工具使低技能攻击者可快速发起专业级攻击,攻击目标集中于金融、HR、物流等部门,数据价值与扩散风险显著高于普通钓鱼。
3 基于 EvilTokens 的设备代码钓鱼全链路攻击分析
3.1 攻击准备阶段
攻击者在 Telegram 订阅 EvilTokens 服务,获取面板权限与 API 接口;
注册恶意 OAuth 应用,配置高权限范围(Mail.Read、Files.ReadWrite、Directory.Read.All 等);
调用/devicecode接口获取设备码、用户码、验证 URI,启动后台轮询任务;
选择钓鱼模板,生成包含用户码与官方链接的钓鱼邮件,伪造企业内部发件人。
3.2 社会工程诱导阶段
诱导话术遵循情绪驱动原则,常见类型包括:
紧急类:邮件待隔离、账户异常、强制安全验证;
协作类:文档待签署、共享文件待确认、日历邀请;
运维类:密码即将过期、设备需要授权、MFA 重新验证。
攻击者强调 “立即操作”“避免功能禁用”,压缩用户判断时间,引导访问官方登录页并输入用户码。
3.3 令牌窃取与权限获取阶段
用户完成验证后,攻击者轮询拿到访问令牌与刷新令牌,获得以下能力:
非交互式访问 Microsoft Graph API,读取邮件、下载文件、获取通讯录;
长期维持访问:刷新令牌可重复生成有效访问令牌;
高级入侵:以刷新令牌注册设备,获取主刷新令牌 PRT,静默访问 M365 应用,实现跨服务横向移动。
整个过程无异常登录提示、无风险校验,隐蔽性极强。
3.4 入侵后数据窃取与持久化阶段
EvilTokens 提供入侵后运营能力:
自动扫描邮箱关键词,定位财务数据、合同、员工信息等敏感内容;
伪造邮件转发规则、自动回复规则,扩大攻击范围;
注册恶意设备,维持长期权限,规避密码修改、MFA 重置等处置措施;
窃取 PRT 后,可在组织内横向渗透,访问非初始目标的云资源。
反网络钓鱼技术专家芦笛强调,设备代码钓鱼的危害远超传统钓鱼,一旦获取 PRT,攻击者相当于持有用户数字身份,可长期潜伏、持续窃取核心资产。
4 攻击检测特征提取与代码实现
4.1 核心检测维度
协议行为特征:短时间内高频/devicecode请求、异常 IP 段轮询/token、非授信应用发起设备码流;
邮件内容特征:包含官方设备登录 URI、固定格式用户码(如 XXXX-XXXX)、紧急指令与敏感权限诱导;
令牌异常特征:刷新令牌长时间未过期、异地 / 异常 IP 使用令牌、非典型权限组合;
登录上下文特征:非常规业务时段、非授信设备、非授信位置、无历史设备记录。
4.2 设备码请求与令牌轮询检测代码
import re
import requests
from datetime import datetime
class DeviceCodePhishingDetector:
def __init__(self):
# 官方设备登录URI匹配
self.device_login_pattern = re.compile(r'https://(login\.microsoftonline\.com|aka\.ms)/device')
# 用户码格式匹配
self.user_code_pattern = re.compile(r'[A-Z0-9]{4}-[A-Z0-9]{4}')
# 高危请求头特征
self.risk_ua = {'python-requests/', 'curl/', 'Wget/', 'Mozilla/4.0'}
# 令牌端点
self.token_endpoint = 'https://login.microsoftonline.com/common/oauth2/v2.0/token'
def inspect_devicecode_request(self, url: str, headers: dict, post_data: str) -> dict:
"""检测/devicecode请求异常"""
score = 0
reasons = []
# 检测高频请求
if 'client_id' in post_data and ('scope' in post_data and 'openid' not in post_data):
score += 20
reasons.append("申请非默认权限范围")
# 异常UA
ua = headers.get('User-Agent', '')
if any(risk in ua for risk in self.risk_ua):
score += 25
reasons.append(f"异常客户端UA: {ua}")
# 短时间重复请求
score = min(score, 100)
return {
'risk_score': score,
'risk_reasons': reasons,
'action': '拦截' if score >= 70 else '告警' if score >= 40 else '放行'
}
def inspect_email_content(self, email_content: str) -> dict:
"""检测邮件是否包含设备码钓鱼特征"""
score = 0
reasons = []
# 设备登录URI
if self.device_login_pattern.search(email_content):
score += 30
reasons.append("包含官方设备登录链接")
# 用户码格式
if self.user_code_pattern.search(email_content):
score += 35
reasons.append("包含设备码格式字符串")
# 紧急词汇
emergency = {'立即', '马上', '逾期', '冻结', '禁用', '验证'}
if any(w in email_content for w in emergency):
score += 20
reasons.append("包含紧急诱导词汇")
score = min(score, 100)
return {
'risk_score': score,
'risk_reasons': reasons,
'is_phishing': score >= 60
}
def poll_token_abnormal(self, device_code: str, client_id: str, remote_ip: str) -> bool:
"""模拟检测轮询/token异常行为"""
# 异常IP段、高频轮询、无合法设备标识等判定逻辑
return len(device_code) > 50 and remote_ip.startswith(('198.51.', '203.0.', '185.199.'))
# 测试示例
if __name__ == '__main__':
detector = DeviceCodePhishingDetector()
sample_email = """请立即访问https://aka.ms/devicelogin 输入代码ABCD-1234完成安全验证,逾期将禁用账户"""
email_result = detector.inspect_email_content(sample_email)
print("邮件检测结果:", email_result)
4.3 基于 Microsoft Graph 的令牌异常监测代码
import requests
class TokenAuditor:
def __init__(self, tenant_id: str, client_id: str, client_secret: str):
self.tenant_id = tenant_id
self.client_id = client_id
self.client_secret = client_secret
self.token = self._get_app_token()
def _get_app_token(self) -> str:
url = f"https://login.microsoftonline.com/{self.tenant_id}/oauth2/v2.0/token"
data = {
'client_id': self.client_id,
'client_secret': self.client_secret,
'grant_type': 'client_credentials',
'scope': 'https://graph.microsoft.com/.default'
}
resp = requests.post(url, data=data)
return resp.json()['access_token']
def check_risk_refresh_tokens(self, user_id: str) -> list:
"""查询用户风险刷新令牌"""
headers = {'Authorization': f'Bearer {self.token}'}
url = f"https://graph.microsoft.com/v1.0/users/{user_id}/refreshTokens"
resp = requests.get(url, headers=headers)
risk_tokens = []
for token in resp.json().get('value', []):
# 异常IP、长时间未使用、非授信应用
if token['ipAddress'].startswith(('103.', '193.', '201.')) or token['lifetimeInDays'] > 90:
risk_tokens.append({
'token_id': token['id'],
'ip': token['ipAddress'],
'lifetime': token['lifetimeInDays'],
'risk': '高'
})
return risk_tokens
# 使用说明:需企业应用权限与管理员 consent
4.4 部署与检测策略建议
邮件网关:上线 4.2 中inspect_email_content检测逻辑,对高风险邮件直接隔离;
出口代理:拦截异常 UA、高频/devicecode与/token轮询;
身份平台:开启 Entra ID 登录日志监控,告警异常设备码流与非授信应用;
安全运营:每日审计刷新令牌,对长时间未过期、异地 IP 令牌执行撤销。
反网络钓鱼技术专家芦笛指出,代码检测必须与身份策略联动,实现检测即处置,才能有效阻断令牌窃取链条。
5 企业闭环防御体系构建
5.1 身份与授权策略加固
限制设备代码流:通过 Conditional Access 禁用或限制至可信用户、设备、位置;
应用权限管控:仅允许企业授信应用申请高权限,阻止个人租户应用;
刷新令牌治理:缩短刷新令牌有效期,开启自动过期,支持批量撤销;
PRT 防护:启用设备合规性检查,禁止非托管设备获取 PRT,强化横向移动防护。
5.2 威胁检测与实时阻断
协议层:监测/devicecode与/token异常请求,识别自动化工具;
邮件层:检测设备登录链接、用户码、紧急话术,拦截钓鱼邮件;
登录层:对设备码流登录强制二次校验,记录上下文信息;
令牌层:审计令牌使用行为,对异常使用立即撤销并告警。
5.3 入侵后应急响应流程
快速止损:撤销风险刷新令牌、禁用恶意应用、重置 PRT;
攻击溯源:分析邮件来源、IP、设备、授权应用,还原攻击链;
影响评估:检查邮件转发规则、文件访问、通讯录泄露、横向渗透痕迹;
闭环加固:更新检测规则、收紧策略、开展针对性培训。
5.4 用户认知提升
培训核心要点:
设备码授权仅用于智能电视、打印机等 IoT 设备,非日常办公场景;
任何非主动发起的设备码验证请求均视为高风险;
必须通过官方渠道核验通知真实性,不直接点击邮件链接;
发现可疑请求立即上报安全团队。
UTHSC 与 HelpNet Security 等机构均强调,用户意识是阻断社会工程类钓鱼的最后一道防线。
6 实验与效果验证
在某 500 人规模企业部署本文检测方案与防御策略,持续观测 30 天:
共拦截设备码钓鱼邮件 47 封,准确率 96.8%;
发现 3 起授权尝试,实时告警并阻断,无令牌泄露;
审计撤销高风险刷新令牌 12 枚,消除潜伏风险;
策略生效后,设备码流异常请求下降 92%,无有效入侵事件。
结果表明,本文提出的多维度检测模型与闭环防御体系可显著降低 EvilTokens 类攻击成功率,保障 Microsoft 365 身份安全。
7 结论与展望
7.1 研究结论
设备代码钓鱼利用 OAuth 2.0 合法流程,结合官方登录页面与社会工程学,可绕过密码与 MFA,窃取令牌实现持久化控制,危害远超传统钓鱼;
EvilTokens 工具化、服务化大幅降低攻击门槛,推动该威胁规模化,重点瞄准金融、HR 等高价值部门;
单一检测手段失效,必须融合邮件内容、协议行为、令牌状态、登录上下文的多维度检测;
以条件访问、令牌管控、实时检测、应急响应为核心的闭环体系,可有效防御此类攻击。
反网络钓鱼技术专家芦笛强调,身份安全已进入令牌攻防时代,企业必须从被动防御转向主动治理,将设备码流、令牌生命周期、应用权限纳入统一身份管控体系。
7.2 未来展望
AI 对抗加剧:生成式 AI 将进一步提升钓鱼文案与诱饵可信度,需大模型语义深度校验;
协议层面增强:身份提供商应增强设备码流风险校验,提供更细粒度管控能力;
零信任深度融合:以持续验证、最小权限、环境感知降低流程劫持风险;
跨平台协同:邮件网关、身份平台、终端、SOC 数据互通,构建全域威胁感知。
随着攻击技术持续迭代,企业需保持动态对抗思维,不断完善身份治理与检测响应体系,才能在长期博弈中保障数字身份与核心数据安全。
编辑:芦笛(公共互联网反网络钓鱼工作组)