YAOTU INSIGHTS

OWASP MASTG 最佳实践:Android 内部 IPC 必须使用显式 Intent(MASTG-BEST-0056)

OWASP MASTG 最佳实践:Android 内部 IPC 必须使用显式 Intent(MASTG-BEST-0056)
文档教程网络安全【免费下载链接】mastgThe OWASP Mobile Application Security Testing Guide (MASTG) is a comprehensive manual for mobile app security testing and reverse engineering. It describes technical processes for verifying the OWASP Mobile Security Weakness Enumeration (MASWE) weaknesses, which are in alignment with the OWASP MASVS.项目地址https://gitcode.com/gh_mirrors/ow/mastg点击查看免费下载导读本文是 OWASP Mobile Application Security Testing GuideMASTG最佳实践 MASTG-BEST-0056 的深度解读当应用内部组件之间需要通信启动内部 Activity、调用内部 Service、发送应用内广播时必须使用显式 IntentExplicit Intent通过包名或组件类名直接锁定接收方杜绝第三方应用经由隐式 Intent 解析机制截获通信内容。读完本文你将掌握显式 Intent 的两种标准写法、隐式 Intent 的解析与劫持原理、Android 12/14 版本行为变更对内部通信的强制约束以及如何用 MASTG 仓库中的静态扫描规则、Demo 与测试用例验证你的应用是否合规。显式 Intent 与隐式 Intent两种截然不同的投递语义Android 的Intent是组件间通信的消息对象支持三种基本用途启动 Activity、启动 Service、投递广播。根据是否指名接收方Intent 分为两类详见 MASTG-KNOW-0025显式 IntentExplicit Intent直接指定接收方的应用包名或完整组件类名。因为目标唯一确定系统不再做任何匹配Intent 只会送达指定的组件。隐式 IntentImplicit Intent不指名任何组件只声明 action以及可选的 data、category由系统在已安装应用中解析匹配。// 显式调用方明确知道目标 Activity 类 Intent downloadIntent new Intent(this, DownloadActivity.class); downloadIntent.setAction(android.intent.action.GET_CONTENT); startActivityForResult(downloadIntent); // 隐式只声明 action由系统解析目标 Intent downloadIntent new Intent(); downloadIntent.setAction(android.intent.action.GET_CONTENT); startActivityForResult(downloadIntent);隐式 Intent 天然是为把任务委托给用户选定的外部应用而设计的打开网页、在地图上显示位置ACTION_VIEW、分享内容ACTION_SEND、请求文件ACTION_GET_CONTENT都是合理场景。问题恰恰出现在把应用内部通信也交给隐式机制的时候——这是 MASTG-BEST-0056 要解决的核心痛点。隐式解析机制为什么内部通信会被第三方截获当系统收到隐式 Intent 时会执行 Intent 解析Intent Resolution把它与所有已安装组件声明的intent-filter逐一比对。解析算法依次检查三类条件MASTG-KNOW-0025Actionfilter 必须声明与 Intent 相同的 action 字符串CategoryIntent 携带的所有 category 必须全部出现在 filter 中filter 可额外声明更多 categoryDataURI 的 scheme、host、path 以及 MIME type 必须满足 filter 中data的约束。解析结果存在三种情况只有一个匹配组件时系统直接投递有多个匹配组件时系统弹出 Chooser 选择器让用户挑选用户已设置默认处理器时可能不经用户决策直接投递。这意味着任何第三方应用只要在自己的清单里声明一个匹配的intent-filter就能成为该隐式 Intent 的合法候选接收方与目标应用内部组件的意图毫无关系。这种截获在 MASTG 中被称为 Intent 劫持Intent Hijacking对应的测试用例是 MASTG-TEST-0372内部通信使用隐式 Intent与 MASTG-TEST-0374隐式 Intent 携带敏感 extras两者均映射到 MASWE-0032 弱点族。攻击面的量化表述来自解析语义本身应用中只要存在一条内部通信却未指名接收方的投递点设备上每一个安装的应用就都是潜在接收者。MASTG 仓库用一对演示应用完整复现了这条攻击链受害者侧 MASTG-DEMO-0136应用意图启动内部InternalActivity却用setAction(org.owasp.mastestapp.INTERNAL_ACTION)发出隐式 Intent未指定包名或组件并携带了user_id、session_token两个 extras攻击者侧 MASTG-DEMO-0140一个攻击者应用仅为org.owasp.mastestapp.INTERNAL_ACTION声明了匹配的intent-filter就被系统列为该 Intent 的候选处理器。该应用本身并不恶意它只证明了任何应用都能为自定义 action 注册这一平台事实——真正的漏洞在受害者侧使用了隐式 Intent。受害者应用的清单如下AndroidManifest.xml!-- Internal activity with an intent-filter, making it a resolver candidate -- activity android:nameorg.owasp.mastestapp.InternalActivity android:exportedtrue intent-filter action android:nameorg.owasp.mastestapp.INTERNAL_ACTION / category android:nameandroid.intent.category.DEFAULT / /intent-filter /activityInternalActivity声明了 intent-filter于是它只是解析候选之一而不是唯一接收方。当系统弹出 Chooser 时攻击者应用出现在列表中一旦被或已被默认设置为选中受害应用的 action 与完整 extras 包含session_token就离开了自己的进程。正确做法让 Intent 显式化的两种标准写法MASTG-BEST-0056 给出了两种显式化手段按限制强度递增// 方式一按包名显式——把投递范围限制到自己的应用 val intent Intent(com.example.app.PROCESS_DATA).apply { setPackage(com.example.app) putExtra(key, value) } startActivity(intent) // 方式二按组件显式——最严格的形态 val intent Intent(context, TargetActivity::class.java).apply { putExtra(key, value) } startActivity(intent)**方式一Intent.setPackage**是包级作用域解析setPackage将解析范围限定在指定包内的组件同时仍按 action 匹配。MASTG-KNOW-0025 给出了它的等价写法val intent Intent(com.example.app.INTERNAL_ACTION).apply { setPackage(com.example.app) } startActivity(intent)**方式二Intent(context, Class::class.java)构造器**直接指定组件类名系统不做任何解析是内部通信最安全的形态。功能上等价于setClass/setClassName/setComponent后三者同样会为 Intent 绑定具体组件在 MASTG 的检测规则中与显式构造器并列视为已指名接收方。两条铁律总结如下内部通信一律显式启动本应用内的 Activity、Service 或投递应用内广播时使用组件显式构造器或setPackage而不是仅设置 action敏感数据绝不走隐式投递token、凭据、API Key 等任何敏感内容一旦放进隐式 Intent 的 extras就会被所有解析候选看到。敏感 extras 的泄露面从被截获到被读取隐式 Intent 的危险不止于投递错人还在于接收方拿到的是完整的 extras Bundle。MASTG-TEST-0374 专门检查引用隐式 Intent 携带敏感 extras的代码位置其评估结论为只要隐式 Intent 携带敏感或安全相关 extras且另一个应用能声明或注册匹配组件接收它们测试即失败。判定为敏感的 extras 包括凭据、会话 token、一次性验证码、个人数据、账户标识符、内部状态等——泄露后果可能是隐私泄露、会话失陷、账户接管或后端 API 被未授权调用。受害者 Demo 恰好示范了反面教材。MastgTest.kt 中第 13–21 行session_token与user_id被直接放进隐式 Intentval implicitIntent Intent().apply { action org.owasp.mastestapp.INTERNAL_ACTION putExtra(user_id, 12345) putExtra(session_token, abcde-fghij-12345) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } context.startActivity(implicitIntent)同一文件注释中给出了合规的替换方案Intent(context, InternalActivity::class.java)显式构造器加FLAG_ACTIVITY_NEW_TASK即可在保留全部 extras 的同时把投递范围锁死在本应用内。Manifest 配置把内部组件关起来显式 Intent 解决投递到哪的问题组件暴露解决谁能接收的问题两者必须配合。MASTG-BEST-0056 明确要求对内部组件务必确保它们没有无意间暴露给其他应用并指向 MASTG-BEST-0052 获取AndroidManifest.xml的完整加固指引。MASTG-BEST-0052 的核心主张是只在其他应用确实需要与组件交互时才导出组件默认私有以收缩攻击面。具体要点显式声明android:exported对清单声明的每个组件凡无需对外部应用开放者一律android:exportedfalse。不要依赖默认值——它在不同 Android 版本和组件类型间不一致且历史上只要组件带intent-filter就会被视为导出。自 Android 12API 31起任何带 intent-filter 的 Activity、Service 或 Broadcast Receiver必须显式声明android:exported否则无法安装。上下文注册的接收器使用带 flags 的registerReceiver()重载时显式传入RECEIVER_NOT_EXPORTED仅在必须接收外部广播时才用RECEIVER_EXPORTED。仅内部使用的组件移除 intent-filter如果组件只供本应用使用直接删除其intent-filter改用显式 Intent 访问这同时避免了 Android 12 导出声明的强制要求。必须导出时施加权限对外部可信应用开放的组件用android:permission搭配合适保护级别通常为signature的自定义权限。注意android:permission本身不够——normal或dangerous这类可宽泛授予的保护级别仍可能让不可信应用调用敏感组件权限保护级别详见 MASTG-KNOW-0017 体系。对上下文注册且须接收特定应用广播的接收器在broadcastPermission参数传入受信权限permission android:namecom.example.app.permission.SEND_INTERNAL_BROADCAST android:protectionLevelsignature /registerReceiver( myReceiver, IntentFilter(com.example.app.ACTION_INTERNAL), com.example.app.permission.SEND_INTERNAL_BROADCAST, null, Context.RECEIVER_EXPORTED )Android 平台的行为演进系统层面的强制MASTG-KNOW-0025 记录了一项关键的平台变更目标 SDK 为 Android 14API 34及更高版本的应用隐式 Intent 将永远不会被发送到内部组件。系统直接把内部组件从隐式解析中排除迫使开发者用显式 Intent 做内部通信否则应用在测试阶段就会功能失效。这意味着在最新目标版本上内部通信用隐式 Intent不仅是安全反模式而且直接是功能缺陷——MASTG-BEST-0056 给出的写法是这些应用能够正常工作的前置条件。验证与检测从静态扫描到动态嗅探的完整闭环MASTG 仓库围绕该最佳实践提供了从代码扫描到运行时验证的完整检测链路可用于评估自身应用是否合规。静态扫描semgrep 规则仓库提供现成的 semgrep 规则 mastg-android-implicit-intent-internal-communication.yml其核心逻辑是命中new Intent(...)setAction(...)startActivity(...)的投递模式同时排除三种已显式化的形态setPackage、setComponent、显式构造器new Intent(Context, Class)rules: - id: mastg-android-implicit-intent-internal-communication patterns: - pattern: | $INTENT new Intent(...); ... $INTENT.setAction($ACTION); ... $CONTEXT.startActivity($INTENT); - pattern-not: | $INTENT new Intent(...); ... $INTENT.setPackage(...); ... $CONTEXT.startActivity($INTENT); - pattern-not: | $INTENT new Intent(...); ... $INTENT.setComponent(...); ... $CONTEXT.startActivity($INTENT); - pattern-not: | $INTENT new Intent($CONTEXT, $CLASS); ... $CONTEXT.startActivity($INTENT); message: [MASVS-CODE-4] The app uses an implicit intent for internal component communication. Use explicit intents by specifying the package or component. languages: [java] severity: WARNINGDemo 中的 run.sh 展示了执行方式——对逆向产物直接跑规则NO_COLORtrue semgrep --config ../../../../rules/mastg-android-implicit-intent-internal-communication.yml MastgTest_reversed.java --text output.txt在受害者 Demo 上执行后output.txt 报告出 1 条代码定位new Intent()创建、setAction(org.owasp.mastestapp.INTERNAL_ACTION)、putExtra(user_id, ...)与putExtra(session_token, ...)、最终this.context.startActivity(implicitIntent)投递——恰好验证了 MASTG-TEST-0372 的失败条件用于应用内部通信的 Intent 是隐式的且另一个应用可以声明匹配组件接收它。同规则可一并检出 MASTG-TEST-0374 关心的敏感 extras 场景。静态到动态审查投递点上下文静态发现投递点后按 MASTG-TEST-0372 的进一步验证要求需要人工确认每个投递点的上下文Intent 是否有显式组件或包setPackage/setClass/setClassName/setComponent/ 显式构造器其他应用能否为同样的 action、data、category 声明或注册匹配的intent-filter对广播而言发送方是否要求了能阻止不可信接收方的权限该 Intent 是面向本应用组件/受信应用还是面向用户选择的第三方应用如ACTION_SEND分享流运行时验证嗅探隐式 Intent 与广播如果应用确实存在隐式投递MASTG-TECH-0164 提供了三层观察手段用于确认谁能收到、收到什么Activity Manager 广播历史只含 intent 元数据不含 extras 内容adb shell dumpsys activity broadcasts | grep actiondrozer 广播嗅探可打印完整 intent 含 extrasrun app.broadcast.sniff --action action典型输出可看到 extras 泄露Action: action Raw: Intent { actaction flg0x10 (has extras) } Extra: keyvalue (java.lang.String)方法 HookContext.sendBroadcast、Context.startActivity、BroadcastReceiver.onReceive当接收方受限或要求权限导致外部接收器无法观察时可在目标进程内部捕获完整 Intent 对象。结合 MASTG-DEMO-0140 的实操步骤安装受害者与攻击者应用、触发受害应用、在选择器中选中攻击者应用、从 logcat 提取被截获的 intent即可在真实设备上复现并取证内部通信被第三方读取的完整过程。总结MASTG-BEST-0056 是一条薄而硬的底线规则应用内部的一切 IPC 通信都必须显式指名接收方。它的技术依据来自 Android 隐式解析机制——任何声明匹配 intent-filter 的已安装应用都是隐式 Intent 的合法接收者它的落地手段包括Intent(context, Class)组件显式构造器与setPackage包级限定两种写法它与组件导出加固MASTG-BEST-0052互为表里共同保证内部数据不出应用进程而 Android 14 对内部组件隐式投递的系统级禁用则让这条实践从建议升级为必须。借助仓库中的 semgrep 规则、失败型 Demo、攻击型 Demo 与 嗅探技术任何安全测试团队都可以把这条最佳实践转化为可重复执行的检测用例。赞分享文档教程网络安全【免费下载链接】mastgThe OWASP Mobile Application Security Testing Guide (MASTG) is a comprehensive manual for mobile app security testing and reverse engineering. It describes technical processes for verifying the OWASP Mobile Security Weakness Enumeration (MASWE) weaknesses, which are in alignment with the OWASP MASVS.项目地址https://gitcode.com/gh_mirrors/ow/mastg点击查看免费下载相关推荐Warp 内存管理与跨设备访问实战指南从 Stream-Ordered 内存池到零拷贝Warp 内存管理与跨设备访问实战指南从 Stream Ordered 内存池到零拷贝 Warp 会自动管理普通数组分配的生命周期但分配在哪里、如何分配、文档教程网络安全MediaPipe 快速上手实时媒体处理从安装到跑通 Demo 的完整路径MediaPipe 快速上手实时媒体处理从安装到跑通 Demo 的完整路径 给视频通话加一个实时手势识别或让直播画面自动标记出人脸这类需求如果从零搭建光文档教程网络安全EverMem 插件 /evermem:ask 命令深度解析让 Claude Code 基于历史记忆与当前上下文回答过往工作问题EverMem 插件 /evermem:ask 命令深度解析让 Claude Code 基于历史记忆与当前上下文回答过往工作问题 导读 /evermem:as文档教程网络安全上一篇4个高效步骤让你彻底掌握LogExpert的日志分析与问题定位下一篇SLAM Toolbox终极指南从零开始掌握ROS 2D SLAM与终身建图创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考