- 文档
- 教程
- 网络安全
【免费下载链接】mastg
The 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.
导读
通知(Notification)是 Android 应用展示信息的重要渠道,但也是敏感数据泄露的高发区:姓名、手机号、验证码、健康或金融信息一旦出现在通知标题或正文中,就可能被旁人窥屏(shoulder surfing)或共享设备时泄露。本文以 OWASP MASTG 仓库中的演示用例 MASTG-DEMO-0078 为主线,完整演示如何对一个故意包含 PII 的 Android 示例应用执行静态分析:从还原后的 Java 代码与 Manifest 清单入手,使用 Semgrep 规则自动定位setContentTitle/setContentText调用点与POST_NOTIFICATIONS权限声明,并结合minSdkVersion判定测试结论。读完本文,你将掌握一套可直接复制的"通知敏感数据泄露"检测命令、规则与判定方法。
背景:通知泄露敏感数据为什么值得专门检测
通知的展示具有"无感可见"的特点——锁屏界面、状态栏、下拉通知栏都会直接渲染通知内容,用户很难控制其可见范围。因此,MASTG-TEST-0315 专门验证应用是否正确处理通知,确保 PII(个人身份信息)、OTP(一次性密码)以及健康、财务等敏感数据不会通过通知暴露。该测试对应 MASVS-PLATFORM-3 安全要求(确保通知不包含敏感信息),并关联 MASWE-0037 弱点枚举项。
本演示用例的核心价值在于:它构造了一个"测试失败的样本"——示例代码刻意把"Hi John Doe"(名 + 姓,属于典型 PII)写进通知标题和正文,并通过 Semgrep 规则在还原后的代码上自动定位这些位置,最终得出测试失败的结论。这为安全测试人员提供了一条"样本 → 工具 → 证据 → 判定"的完整链路。
示例应用剖析:四条路径把 PII 写进通知
示例源码位于 MastgTest.kt,它用四种方式构造通知,覆盖了 Android 通知 API 的常见组合:
Notification.Builder(无通知渠道 / 指定渠道)NotificationCompat.Builder(AndroidX 兼容实现,无渠道 / 指定渠道)
package org.owasp.mastestapp import android.R import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager import android.content.Context import androidx.core.app.NotificationCompat class MastgTest(private val context: Context) { val notificationManager = (context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).apply { createNotificationChannel( NotificationChannel( "TEST_CHANNEL_ID", "Test Channel", NotificationManager.IMPORTANCE_DEFAULT ) ) } val sensitiveTitle = "Hi John Doe" val sensitiveText = "Hi John Doe <- This is a sensitive string containing PII" fun mastgTest(): String { notificationManager.notify(1, createNotification()) notificationManager.notify(2, createNotificationOnChannel()) notificationManager.notify(3, createNotificationCompat()) notificationManager.notify(4, createNotificationCompatOnChannel()) return sensitiveText } private fun createNotification() = Notification.Builder(context) .setContentTitle(sensitiveTitle) .setContentText(sensitiveText) .setSmallIcon(R.drawable.ic_menu_info_details) .build() private fun createNotificationOnChannel() = Notification.Builder(context, "TEST_CHANNEL_ID") .setContentTitle(sensitiveTitle) .setContentText(sensitiveText) .setSmallIcon(R.drawable.ic_menu_info_details) .build() private fun createNotificationCompat() = NotificationCompat.Builder(context) .setContentTitle(sensitiveTitle) .setContentText(sensitiveText) .setSmallIcon(R.drawable.ic_menu_info_details) .build() private fun createNotificationCompatOnChannel() = NotificationCompat.Builder(context, "TEST_CHANNEL_ID") .setContentTitle(sensitiveTitle) .setContentText(sensitiveText) .setSmallIcon(R.drawable.ic_menu_info_details) .build() }关键点在于:四种构造方式全部复用了同一个sensitiveTitle与sensitiveText。这意味着只要静态规则能命中setContentTitle/setContentText调用,就能发现全部泄露点,而无需逐一阅读方法体。此外,示例通过NotificationChannel("TEST_CHANNEL_ID", ..., IMPORTANCE_DEFAULT)创建了通知渠道,并分别在有无渠道两种场景下调用notify(),模拟了真实应用中"老接口迁移到渠道机制"的常见状态。
清单声明:POST_NOTIFICATIONS 与目标版本
示例应用的 AndroidManifest.xml 中声明了两个与通知相关的权限/配置:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />POST_NOTIFICATIONS是 Android 13(API 33)及更高版本引入的运行时权限:面向 API 33 及以上目标版本的应用,必须先请求该权限才能发布通知;API 33 以下的系统版本则不要求此权限。因此测试阶段必须确认该权限已被授予(详见下文"前置条件")。
而从还原后的 AndroidManifest_reversed.xml 可以看到实际打包产物中的版本信息:
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="35"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>minSdkVersion="29"是评估环节的关键输入,其含义在判定逻辑一节详细展开。
前置条件:确保应用获得通知权限
原文档特别提示:在设备上执行测试前,必须确保应用已获得POST_NOTIFICATIONS权限。两种途径任选其一:
- 通过 adb 命令行直接授权:
adb shell pm grant org.owasp.mastestapp android.permission.POST_NOTIFICATIONS- 在设备上进入 设置 → 应用 → 该应用 → 通知,手动开启通知权限。
说明:
adb shell pm grant适用于android.permission.POST_NOTIFICATIONS这类可授予权限;如果应用已声明但未在运行时请求,此命令仍可强制授予,方便测试场景绕过 UI 交互。
静态分析规则:两条 Semgrep 规则
MASTG 为通知敏感数据场景提供了两条 Semgrep 规则,均位于 rules 目录:
规则一:扫描代码中的通知内容 API
rules/mastg-android-sensitive-data-in-notifications.yml 针对 Java/Kotlin 反编译代码,命中setContentTitle与setContentText两类 API 调用:
rules: - id: mastg-android-sensitive-data-in-notifications languages: - java severity: WARNING metadata: summary: This rule looks for notifications that may contain sensitive data. message: "[MASVS-PLATFORM-3] Ensure that notifications do not contain sensitive information" pattern-either: - pattern: $X.setContentTitle(...) - pattern: $X.setContentText(...)pattern-either表示任一模式命中即告警;$X是元变量,可匹配任意接收者对象,因此无论是Notification.Builder还是NotificationCompat.Builder都能命中;- 规则声明为
WARNING级别,输出时会附带[MASVS-PLATFORM-3]消息前缀,便于与安全要求对应。
规则二:扫描清单中的权限声明与最低版本
rules/mastg-android-sensitive-data-in-notifications-manifest.yml 包含两条 XML 规则:
rules: - id: mastg-android-sensitive-data-in-notifications-manifest languages: - xml severity: WARNING metadata: summary: This rule inspects AndroidManifest.xml for notification post permission. Notification may contain sensitive data. message: "[MASVS-PLATFORM-3] Ensure that notifications do not contain sensitive information" pattern: android:name="android.permission.POST_NOTIFICATIONS" - id: mastg-android-minsdkversion languages: - xml severity: INFO metadata: summary: This rule inspects AndroidManifest.xml to obtain the minSdkVersion value. message: "[MASVS-PLATFORM-3] Ensure that the minSdkVersion is evaluated for notification exposure on older Android versions" pattern: android:minSdkVersion="$X"- 第一条命中
POST_NOTIFICATIONS权限声明(WARNING); - 第二条提取
minSdkVersion值(INFO级别,因为它的作用是获取评估所需的版本输入,而非直接告警)。
执行步骤:运行 Semgrep 规则
MASTG 的演示统一通过 run.sh 执行静态扫描,工具是 semgrep——一款可扫描 Java、Kotlin、Swift 等语言的静态代码扫描器:
NO_COLOR=true semgrep -c ../../../../rules/mastg-android-sensitive-data-in-notifications.yml ./MastgTest_reversed.java --text > output.txt NO_COLOR=true semgrep -c ../../../../rules/mastg-android-sensitive-data-in-notifications-manifest.yml ./AndroidManifest_reversed.xml --text > output2.txt命令要点:
- 扫描对象是还原后的
MastgTest_reversed.java与AndroidManifest_reversed.xml,模拟真实测试中"拿到 APK → 反编译 → 对还原产物做静态分析"的流程; -c指定规则文件,--text以纯文本格式输出,NO_COLOR=true禁用 ANSI 颜色,便于脚本化收集结果;- 结果分别写入
output.txt(代码规则)与output2.txt(清单规则)。
实战提示:真实项目中
MastgTest_reversed.java对应的是用 jadx、apktool 等工具还原出的整个应用源码与 Manifest,规则路径与扫描目标请按项目实际情况调整。
观察结果解读:规则命中在哪里
代码扫描结果(output.txt)
规则在还原后的 Java 代码中报告了4 处 Code Findings,全部集中在 MastgTest_reversed.java:
┌─────────────────┐ │ 4 Code Findings │ └─────────────────┘ MastgTest_reversed.java ❯❱ rules.mastg-android-sensitive-data-in-notifications [MASVS-PLATFORM-3] Ensure that notifications do not contain sensitive information 41┆ Notification notificationBuild = new Notification.Builder(this.context).setContentTitle("MASTG Test").setContentText(sensitiveString).build(); ⋮┆---------------------------------------- 41┆ Notification notificationBuild = new Notification.Builder(this.context).setContentTitle("MASTG Test").setContentText(sensitiveString).build(); ⋮┆---------------------------------------- 48┆ Notification notificationBuild = new Notification.Builder(this.context, "TEST_CHANNEL_ID").setContentTitle("MASTG Test").setContentText(sensitiveString).build(); ⋮┆---------------------------------------- 48┆ Notification notificationBuild = new Notification.Builder(this.context, "TEST_CHANNEL_ID").setContentTitle("MASTG Test").setContentText(sensitiveString).build();与原文档观察一致:2 处setContentTitle调用、2 处setContentText调用(第 41 行与第 48 行各同时含标题与正文两个模式命中,故 4 条)。注意还原后的代码中,setContentText(sensitiveString)参数来自反编译变量——它正是 Kotlin 源码中sensitiveText的还原形态,内容即 PII 字符串。
清单扫描结果(output2.txt)
清单规则报告2 处 Findings:
┌─────────────────┐ │ 2 Code Findings │ └─────────────────┘ AndroidManifest_reversed.xml ❱ rules.mastg-android-minsdkversion [MASVS-PLATFORM-3] Ensure that the minSdkVersion is evaluated for notification exposure on older Android versions 11┆ android:minSdkVersion="29" ❯❱ rules.mastg-android-sensitive-data-in-notifications-manifest [MASVS-PLATFORM-3] Ensure that notifications do not contain sensitive information 14┆ <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>- 第 11 行:
minSdkVersion="29"(INFO,评估输入); - 第 14 行:
POST_NOTIFICATIONS权限声明(WARNING)。
评估与判定:测试为何失败
根据 MASTG-TEST-0315 的判定标准,只要通知暴露了敏感数据,并且满足以下任一条件即判定失败:
minSdkVersion为33 或更高,且清单中声明了POST_NOTIFICATIONS权限;或minSdkVersion为32 或更低,无论是否声明该权限。
本示例中:还原代码第 41、48 行确认通知内容包含"Hi John Doe"(名 + 姓,属于 PII);清单显示minSdkVersion="29"(≤ 32)。因此测试判定为失败(test fails)——即使不依赖权限声明条件,29 这一低版本下限也足以构成泄露风险。
为什么用 minSdkVersion 而不是 targetSdkVersion
这是 MASTG-TEST-0315 专门解释的设计取舍:
minSdkVersion决定了应用可运行的最低 Android 版本,代表应用可能运行的最不安全环境,这才是真实暴露风险的边界;targetSdkVersion只影响应用在新版本系统上的行为与平台限制的强制程度,不会改变旧版本系统的行为。
因此,一个targetSdkVersion很高但minSdkVersion很低的应用,仍必须按旧版本的安全保证(或者说缺乏保证)来评估。本示例minSdkVersion=29正属于"无论权限如何声明,通知泄露都判定失败"的区间。
修复方向:参考 MASTG-BEST-0027
OWASP MASTG 为该场景提供了最佳实践条目 MASTG-BEST-0027(Preventing Sensitive Data Exposure in Notifications),其核心思路包括:
- 彻底避免在通知内容中放入敏感数据(本示例即违背此原则);
- 若必须展示,则设置适当的可见性级别(visibility),控制通知在锁屏等场景的显示粒度;
- 测试时还应结合 identify-sensitive-data 前置任务,明确应用处理了哪些敏感数据类型,以便对每个泄露点给出有依据的判定。
小结:一条可复制的检测链路
通过 MASTG-DEMO-0078,可以沉淀出检测"通知泄露敏感数据"的完整闭环:
- 还原:对 APK 反编译,得到 Java 源码与 AndroidManifest.xml(参见示例中的 MastgTest_reversed.java 与 AndroidManifest_reversed.xml);
- 扫描:用 semgrep 加载两条规则,分别扫描代码(
setContentTitle/setContentText)与清单(POST_NOTIFICATIONS/minSdkVersion); - 定位:根据输出中的文件与行号(本示例为第 41、48 行)人工复核通知内容;
- 判定:结合
minSdkVersion与权限声明,按 MASTG-TEST-0315 的失败条件得出结论; - 修复:对照 MASTG-BEST-0027 消除暴露或限制可见性。
这套方法不依赖设备交互即可发现"代码层面是否存在泄露通道",是 MASVS-PLATFORM-3 合规评估中性价比最高的起点;如需验证运行时真实展示效果,可再配合真机/模拟器上的动态观察进行补充确认。
- 文档
- 教程
- 网络安全
【免费下载链接】mastg
The 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.
相关推荐
OWASP MASTG 最佳实践:防止 Android 通知中的敏感数据泄露(MASTG-BEST-0027)
OWASP MASTG 最佳实践:防止 Android 通知中的敏感数据泄露(MASTG BEST 0027) 本指南基于 OWASP Mobile Appli
文档教程网络安全OWASP MASTG 实战:Android 内部存储明文敏感数据检测(MASTG-DEMO-0010 / MASTG-TEST-0207)
OWASP MASTG 实战:Android 内部存储明文敏感数据检测(MASTG DEMO 0010 / MASTG TEST 0207) 导读 本文以 OW
文档教程网络安全OWASP MASTG 实战:用 Semgrep 静态检测 Android StrictMode 使用(MASTG-DEMO-0039)
OWASP MASTG 实战:用 Semgrep 静态检测 Android StrictMode 使用(MASTG DEMO 0039) 导读 :本文基于 OW
文档教程网络安全
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考