2026 年 9 月 28 日,GitHub Security Lab 的 Kevin Stubbings 发了一篇复盘,讲他们怎么用一套自己写的开源 AI 审计流程,在 Android 应用里找漏洞并上报了 24 个。文章里挑了两个已经披露的案例,一个能让第三方应用悄无声息地追踪你的位置,另一个能接管你的 Wikipedia 账户,而且都能在用户毫无察觉的情况下完成。
这件事的意义不在于数字本身,而在于它展示了一种可复制的流程:把安全研究员的经验拆成增量步骤,塞进专门的 prompt,再交给大模型去跑。GitHub 强调,这类自定义任务流能让模型更快找到复杂漏洞,或者找到它原本会漏掉的漏洞。下面按官方原文梳理。
两阶段审计流程
这套流程的核心思路是两阶段,而且专门针对移动端攻击面做了校准。
第一阶段用 gather_mobile_entry_point_info.yaml 这个任务流,从混合代码库里把移动端特有的入口点(Activity、Service、BroadcastReceiver)和通用的应用端点区分开。这么做的目的是聚焦移动攻击面,不去浪费 token 分析无关代码,也让 AI 能在同一个仓库存放多种应用类型(移动应用、Web 服务、桌面应用)时仍理解正确的攻击面。
第二阶段用 classify_application_local.yaml,引导模型逐一检查已知的 Android 漏洞类别。官方举的例子包括 intent 注入相关的混淆代理(confused deputy)和不安全广播。因为移动端漏洞的公开资料相对少,而模型是非确定性的,这一步用固定的漏洞类别清单来兜底,确保明显的问题不被漏掉。
作者的原话是,把这两种 prompt 结合、多次运行,能同时拿到两种好处:严格的 prompt 加上重复运行,保证明显漏洞不被遗漏;宽泛的 prompt 则让 AI 把创造力发挥出来。
已披露案例一:OsmAnd 的位置追踪
OsmAnd 是一款用 OpenStreetMap 数据的热门导航应用,Android 版下载量超过一千万。在它身上,团队一共发现三个漏洞,这里讲最有趣的那个:恶意应用可以追踪设备位置。
问题出在一个被导出的 activity 上。OsmAnd 导出了 MapActivity,而导出意味着它能被自身应用之外的组件启动。这个 activity 在处理设置文件导入时,会用到一个叫 handleOsmAndSettingsImport 的函数,它从 intent extras 里读取几个值:settings_version、silent_import、replace、export_type_list_key。官方指出,这些 extras 本来只该来自一个 AIDL 服务,应该走进程内通道传递。用 intent extras 的问题是,任何应用都能给任意导出 activity 的任意 intent 塞进任意 extras,Android 本身没有机制限制外部调用者能设置哪些 extras。
后果是可以静默导入任意设置。其中 silent_import 让导入不弹通知,replace 允许直接替换而不是追加设置,settings_types 让导入不需要用户确认。把这些组合起来,攻击者就能改掉地图瓦片的来源。OsmAnd 拼接每个瓦片的 URL 时用的是 MessageFormat.format(urlTemplate, zoom, x, y),默认走本地瓦片,但只要把默认瓦片文件覆盖成指向攻击者域名的模板,攻击者就能拿到用户加载过的每一个瓦片的 x、y 坐标。瓦片坐标可以反推出经纬度,于是用户的位置和每一次出行的起终点都会流向攻击者服务器,而用户对此毫不知情。
官方强调,任何应用,哪怕一个没有任何权限的应用,都能借这条路改写 OsmAnd 的设置并把私密位置数据发回自己的服务器。
已披露案例二:Wikipedia 的账户接管
第二个案例是 Wikipedia 的 Android 应用。它注册了 wikipedia:// 这个 deeplink,用来在应用内打开维基百科页面。问题在主机名解析:处理逻辑判断 it.authority.orEmpty().endsWith(WikiSite.BASE_DOMAIN),只要主机名以 base domain 结尾就放行。这个逻辑缺陷允许加载非维基百科的 URL,配套的还有一处 cookie 域校验的同类问题,判断条件写成 domain.endsWith(domainSpec)。
两个问题串起来,就成了一条完整的攻击链。
- 受害者在浏览器里打开一个恶意网页,网页里带一个 deeplink,用户点击。
- Wikipedia 应用被唤起,加载一个以
wikipedia.org结尾的攻击者页面,例如evil-wikipedia.org,用户以为还在维基百科上。 - 应用自动把这个页面的 cookie 发出去,攻击者拿到用户名、长效令牌,以及一个在全部 Wikimedia 项目(所有语言的维基百科、Commons、Wikidata、Meta 等)都有效的会话令牌。
这套链路里,攻击者还能在应用的 WebView 里执行任意 JavaScript,等于拿到了进入本该安全环境的入口。官方把这个漏洞模式的价值点说得很清楚:模型找到的不是笼统的 bug 类别,而是有严重影响的逻辑漏洞。
怎么自己跑一遍
任务流是开源的,作者给出了一套最小上手路径。在 seclab-taskflows 仓库里开一个 codespace,等几分钟初始化,然后在终端执行:
./scripts/audit/run_mobile.sh myorg/myrepo
中等规模的仓库大概需要一到两个小时。跑完后会打开一个 SQLite 查看器,看 audit_results 表,has_vulnerability 列有勾选的行就是结果。官方特别提醒两点:需要 GitHub Copilot 许可证,也就是会走 premium 模型额度;而且任务流会产生大量工具调用,很容易消耗大量 token。
官方承认的边界:找漏洞强,估严重性弱
GitHub 没有把这套流程包装成万能工具,而是写明了短板,这一点值得照抄。
首先是严重性误判。模型经常报出低危问题,即使被明确要求不要这么做。更麻烦的是它会高估影响。官方的例子是 Android 应用里的一处路径穿越,如果文件路径被限制在外部存储,相对严重性其实很低,但这类缓解因素模型不容易看到,除非明确要求它「写一个 PoC」,而这又需要多次运行,迫使模型真的去尝试利用漏洞。即便如此还是会错,例如应用同时使用内部和外部存储时,内部存储的数据往往优先,模型却可能以为通过路径穿越写入的外部数据会改变应用的实际数据,结果根本不存在漏洞。
其次是误报。复杂应用的行为超出模型的推理能力,缺少调试器访问或人工指导时容易误报。官方给的解法是让模型跑 PoC 并对照原始代码,或者由研究员明确提示模型去排查这类问题。
另一面是它擅长的部分:模型对常见 API 的行为理解得相当好,即使看不到语言源码。官方说,让模型生成的大多数 PoC,在他们手里只需少量修改就能用。这说明它对以往漏洞模式和 API 行为有较深的知识。
综合下来,官方给出的操作原则是:每一条发现都应交给了解移动端的安研人员复核。
对开发者的启示
这两个案例反复指向同一件事,外部输入不能信,导出的组件更是攻击面的收缩重点。可以对照检查以下几项。
- 收紧导出组件。只在必要时导出 Activity 或 Service,用
android:exported="false"把默认值改掉。 - 校验 intent 来源与内容。把 intent extras 一律当作不可信输入,做严格的类型检查和白名单;需要区分调用方时用
getCallingPackage()或签名校验。 - 别让外部 intent 直接改关键设置。敏感操作应走内部通道,而不是暴露成导出的入口。
- URL 的主机名解析要严格。类似
endsWith的判断容易放过evil-wikipedia.org这类域名,需要按标签做精确匹配。
至于 AI 安全工具本身,比较稳妥的定位是自动化初筛加人工确认。官方明确说了发现需要复核,同时提醒 premium 调用成本不低,适合用在关键仓库上。
