高级开发者关系工程师
本演讲探讨了战略转变:从将 AI 视为通用编码助手,转变为将其作为具有上下文感知能力的自动化安全同行评审者,直接集成到 Android 开发生命周期中。我们将讨论通过技能连接到 Android 工具链的专用 AI 智能体如何帮助提高应用安全性。通过弥合原始 LLM 功能与深层项目上下文之间的差距,这种方法使开发团队能够在不影响严格的安全和政策标准的情况下,保持高速的功能交付。
转写文稿
大家好,我是 Kristen。
大家好,我是 Sabs。
今天,我们将与大家探讨智能体时代的安全问题。
在过去一年中,我们为 Android Bug Hunters 计划发放了超过 200 万美元的奖励,为移动设备发放了超过 20 万美元的奖励。
在当今的智能体时代,应用安全形势不断演变。
接下来,我们来谈谈有助于快速有效地解决这些问题的工具。
若要提升智能体在 Android 安全方面的表现,答案并非更好的提示。
它提供各种工具和工作流,可帮助智能体了解我们的工具链和 API,从而保障应用安全。
现在是下午 4:30。
在周四。
您正在发布一个版本,但 CI 变红了,只有一个错误:注册的广播接收器没有导出标志。
因此,无论您是身兼数职的小团队成员,还是在发布版本时才进行安全检查的大团队成员,现实情况都是一样的。
我们是产品工程师,负责快速发布高质量的功能,不一定是安全研究人员。
那么,自然本能是什么?
因此,我们将该警告交给智能体工具,并让智能体提供修复方案。
但智能体工具在没有项目上下文的情况下工作,存在三个盲区。
它可能不知道您的应用是由动态功能模块或多 APK bundle 构建的。
它看到的是一个文件,而不是一个已交付的工件。
它可能无法追踪从 Kotlin 界面到 KMP 共享逻辑,再到原生 C++ JNI 调用的数据流。
它只能看到一层。
最后同样重要的是,它可能不了解您的最低 SDK 或 Gradle build 变体。
因此,我们让智能体查看该应用,并要求其进行安全审核。
系统返回了六项发现结果。
事情是这样的。
他们每一个人的说法都没有错。
这些说法都有道理,但其中只有一个是我们最初遇到的 bug。
其余部分则包含良好实践、需要进一步调查的事项、推测以及可能不适用的事项。
现在,您将该功能扩展到实际代码库中,随着警告数量的增加,在每个拉取请求中,您都会想要使用 suppress lint。
您需要更改才能合并该更改,甚至可能完全错过漏洞。
而这正是真正的漏洞得以蒙混过关的原因。
该工具并非粗心大意,而是小心谨慎,但小心谨慎并不等同于有用。
我们来看一个具体示例。
假设您向智能体发出指令:“审核此应用中每个导出的组件,检查是否存在应用 intent 重定向问题。”
这是一项真正的安全任务,对于多模块应用来说,这是一项艰巨的任务。
这类请求才会产生实际费用。
如果没有针对 Android 的具体指导,智能体就无法回答该问题。
因此,它会进行暴力破解。
它可能会读取根本不导出任何内容的模块。
它可能会根据第一原则重新推导,找出导致 intent 重定向可被利用的原因。
它可能会遵循从未到达过的路径。
您需要为探索付费,而不是为分析付费。
技能可以提供缺失的策略。
例如,Android 安全技能可为智能体提供遵循当前指南的指令,这些指令与安全研究人员实际遵循的步骤顺序相同,从而使智能体不再猜测。
它不会重新发现规则,因为规则是由技能提供的。
目前,我们已推出两项安全技能:Intent 安全和权限。
Intent 安全性涉及其他应用可以使您的应用执行的操作。
您的应用拥有权限,而登录会话没有。
因此,您分发的每个导出组件和每个待处理 intent 都是他人通过您执行操作的潜在途径。
这项技能有助于防范这种情况。
权限技能有助于弥合已声明权限与实际强制执行权限之间的差距。
它可以帮助您编写适当的权限检查。
这有助于识别具有通配符路径的提供程序是否授予了对整个数据库(而非单个目录)的访问权限。
它还会捕获过度请求权限的情况。
例如,在照片选择器即可满足需求的情况下,请求广泛的访问权限。
将其与 Android CLI 搭配使用,然后询问“Audit for intent security”(审核 intent 安全性)。
无任何配置。
没有规则调整。
因此,输出结果不会是一大堆警告。
这是一条评价。
这里有一个 bug,它对您的应用有何影响,以及如何修复。
这里有个专业提示。
使用 Android CLI 可轻松查找和安装。
android skills list
android skills add android-intent-security
android skills add android-permissions-security由于技能确切知道要在项目中查找什么,因此它会看到应用的实际发布状态。
它会遵循您的最低 SDK 版本,以便修复代码能够成功编译,并提供真实的文件路径和行号。
以下是您收到的评价。
它会指出确切的文件和代码行,解释实际威胁和更改原因,而不仅仅是说“Lint 这么说的”。
它会引用所使用的技能。
它读取了 build 配置,发现最低 SDK 版本为 26,并选择了 ContextCompat,因此修复方案有效,并为您提供了差异,以便您应用。
这就是我们一开始看到的警告,但现在它附带了建议的修复方法和更多原因说明。
因此,前面的技能可以捕获安全 bug。
现在,我们来谈谈另一个方面,即应用政策合规性。
例如,假设您是一位新应用开发者,希望在 Play 商店中发布应用。
填写数据安全表单是发布应用的重要步骤,因此,请务必利用所有可用工具,确保在提交应用之前正确填写该表单。
Play 政策技能会对您的代码库执行静态分析。
如果您要发布的是 Play 商店中已有的应用,该工具还可以将静态代码分析结果与 Play 商店声明进行交叉对比。
运行此技能可帮助您在提交应用之前(而非之后)发现潜在的 Google Play 政策问题,从而加快提交流程。
工作流程与我们一直在讨论的其他技能类似:导入应用,然后询问“在我提交此应用之前,请审核其是否符合 Google Play 政策”。
您会在右侧看到一个示例报告的屏幕截图,并在下方看到用于安装该报告的 Android CLI 命令。
android skills list
android skills add play-policy-insights到目前为止,我们讨论的所有内容(审核 intent、检查权限、验证合规性)都是在发布之前进行的。
这就是构建时安全性,它至关重要。
但还有一类威胁,只有在您的 APK 发布到外部世界、在您可能无法控制的设备上运行时才会出现。
Play Integrity API 会在运行时回答您自己的代码无法回答的三个问题:这是您的应用的未经修改的正版 build 吗?
此应用是否在正品 Android 设备上运行?
这是 Google Play 用户账号吗?
因此,您可以使用 Play Integrity API 返回应用完整性、设备完整性等方面的判定结果。
除了让您能够更快速、更轻松地发布更安全的应用之外,我们还让您能够更轻松地保障应用的收入和声誉。
因此,请保护您的业务免受欺诈和滥用行为的侵扰。
全新的“由 Google Play 提供保护”信息中心(如您所见)可帮助您在一个位置集中监控和配置完整性、分发和变现防御措施。
我们还缩短了 Play Integrity API 的预热延迟时间,以便您在对速度要求较高的用户历程中使用这些检查,从而更快地拦截威胁和风险设备。
刚才我们讨论了有助于保障应用安全的 Android 功能和工具,那么用户安全又该如何保障呢?
我们先来看看短信动态密码保护。
假设您想为应用实现基于短信的用户验证,并发送验证码。
短信权限可让应用访问消息数据,包括动态密码等敏感数据。
因此,我们在您的应用中引入了一些 API,以便您实现该功能,这样您就无需请求广泛的短信权限,但仍能获取短信动态密码进行验证。
借助 SMS Retriever API,您的应用无需广泛的短信权限即可自动验证动态密码。
您在消息中附加一个用于标识应用的 11 字符哈希,系统只会将该消息传递给您。
如果您无法控制消息格式,请使用 SMS User Consent API。
系统会显示一个一次性提示。
用户点按“允许”或“拒绝”,如果用户允许,您会收到该单条消息。
仍然不需要宽泛的短信权限。
某些应用可能只需要一次精确位置信息即可完成任务。
现有的单次授权会给用户带来很大不便,因此开发者有时会转而请求更广泛的确切位置信息权限。
因此,位置信息按钮是一种低摩擦的方式,可让用户向应用授予一次性精确位置信息访问权限。
这是一种 Android 界面元素,可由应用开发者进行自定义和嵌入。
我们在 6 月份推出了位置信息按钮 Jetpack 库的第一个 Alpha 版。
在这里,您可以看到在 Android 清单中启用位置信息按钮所需的权限。
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
android:usesPermissionFlags="onlyForLocationButton"/>
<uses-permission android:name="android.permission.USE_LOCATION_BUTTON" />
<application
android:icon="@mipmap/ic_launcher"
android:label="LocationButtonSample"
android:theme="@style/Theme.PinPoint">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>您必须声明标准位置信息权限,即添加 onlyForLocationButton 权限标志,以及系统的远程渲染服务所需的专用 USE_LOCATION_BUTTON 权限。
右侧是实现该功能的 Jetpack 代码。
...
import androidx.core.locationbutton.compose.LocationButton
@Composable
fun LocationPermissionScreen(onPermissionGranted: () -> Unit, onPermissionDenied: () -> Unit) {
// Renders the secure system-trusted Location Button composable
LocationButton(
// Callback triggered when the user taps the secure button and makes a decision on the permission dialog
onPermissionResult = { isGranted ->
if (isGranted) {
onPermissionGranted()
} else {
onPermissionDenied()
}
},
...您可以看到,我们正在创建一个位置信息按钮并初始化一个回调。
当用户点按位置信息按钮以决定是授予还是拒绝权限时,系统会触发此回调。
高级保护模式是一项专为高风险用户或注重安全的用户设计的功能,但任何用户都可以选择启用。
例如,假设您是一款银行应用,您不会在每次转账时都强制要求进行额外的多重身份验证,因为普通用户不喜欢这种额外的麻烦。
但是,当高级保护模式处于开启状态时,您的应用会知道此用户希望获得最高级别的保护,因此您可以自动要求在每次转账时进行生物识别验证。
高级保护模式会实施一组预定义的配置,旨在加强设备保护。
在这里,我们将向您展示如何集成到您的应用中。
您需要请求权限、查询高级保护模式,并使用设备端调用高级保护模式管理器系统服务来检查用户是否已开启高级保护模式。
class AdvancedProtectionManager() {
// Check the current status
fun isAdvancedProtectionEnabled(): Boolean
// Be alerted when status changes
fun registerAdvancedProtectionCallback(executor: Executor,
callback: Callback)
fun unregisterAdvancedProtectionCallback(callback: Callback)
}
interface Callback() {
// Called when advanced protection state changes
fun onAdvancedProtectionChanged(enabled: Boolean)
}然后,您可以通过注册回调来监听运行时更改。
android skills list
android skills add android-intent-security
android skills add android-permissions-securityandroid skills list
android skills add play-policy-insights<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
android:usesPermissionFlags="onlyForLocationButton"/>
<uses-permission android:name="android.permission.USE_LOCATION_BUTTON" />
<application
android:icon="@mipmap/ic_launcher"
android:label="LocationButtonSample"
android:theme="@style/Theme.PinPoint">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>...
import androidx.core.locationbutton.compose.LocationButton
@Composable
fun LocationPermissionScreen(onPermissionGranted: () -> Unit, onPermissionDenied: () -> Unit) {
// Renders the secure system-trusted Location Button composable
LocationButton(
// Callback triggered when the user taps the secure button and makes a decision on the permission dialog
onPermissionResult = { isGranted ->
if (isGranted) {
onPermissionGranted()
} else {
onPermissionDenied()
}
},
...class AdvancedProtectionManager() {
// Check the current status
fun isAdvancedProtectionEnabled(): Boolean
// Be alerted when status changes
fun registerAdvancedProtectionCallback(executor: Executor,
callback: Callback)
fun unregisterAdvancedProtectionCallback(callback: Callback)
}
interface Callback() {
// Called when advanced protection state changes
fun onAdvancedProtectionChanged(enabled: Boolean)
}