- 文档
- 教程
- 网络安全
【免费下载链接】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 仓库中的 MASTG-DEMO-0001 为实战样本,完整演示如何通过「时间戳 + 文件系统快照」技术,在 Android 设备上定位并取证应用写入外部存储的未加密敏感文件。读完本文,你将掌握getExternalFilesDir与MediaStore两种外部存储写入路径的源码级风险识别方法,能够使用 adb 脚本自动化「前后比对」流程,并依据 MASTG-TEST-0200 的标准做出合规性评估。
Demo 定位:一条可复现的外部存储泄露链
MASTG-DEMO-0001(标题为File System Snapshots from External Storage)是 OWASP MASTG 移动应用安全测试指南中用于演示「敏感数据明文落盘外部存储」漏洞的官方样本,它对应 MASTG-TEST-0200(Files Written to External Storage),并覆盖旧版测试用例 MASTG-TEST-0001(Testing Local Storage for Sensitive Data) 中 MSTG-STORAGE-1 与 MSTG-STORAGE-2 的检测范围。
整个 Demo 由以下文件组成(位于 demos/android/MASVS-STORAGE/MASTG-DEMO-0001/):
MastgTest.kt:Kotlin 编写的漏洞样本代码,通过两种 API 向外部存储写入敏感数据;run_before.sh/run_after.sh:基于 adb 的快照捕获与差分脚本;output.txt:应用运行后捕获到的「新增文件清单」;new_files/secret.txt与new_files/secretFile75.txt:从设备拉取到的明文敏感文件。
脆弱样本代码分析:两条写入路径
样本代码位于 MastgTest.kt,属于org.owasp.mastestapp包。核心入口mastgTest()依次调用两个函数,分别对应两种最典型的外部存储写入方式:
package org.owasp.mastestapp import android.content.Context import android.util.Log import java.io.File import java.io.FileOutputStream import java.io.IOException import android.content.ContentValues import android.os.Environment import android.provider.MediaStore import java.io.OutputStream class MastgTest (private val context: Context){ fun mastgTest(): String { mastgTestApi() mastgTestMediaStore() return "SUCCESS!!\n\nFiles have been written with API and MediaStore" } fun mastgTestApi() { val externalStorageDir = context.getExternalFilesDir(null) val fileName = File(externalStorageDir, "secret.txt") val fileContent = "secr3tPa\$\$W0rd\n" try { FileOutputStream(fileName).use { output -> output.write(fileContent.toByteArray()) Log.d("WriteExternalStorage", "File written to external storage successfully.") } } catch (e: IOException) { Log.e("WriteExternalStorage", "Error writing file to external storage", e) } } fun mastgTestMediaStore() { try { val resolver = context.contentResolver var randomNum = (0..100).random().toString() val contentValues = ContentValues().apply { put(MediaStore.MediaColumns.DISPLAY_NAME, "secretFile$randomNum.txt") put(MediaStore.MediaColumns.MIME_TYPE, "text/plain") put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS) } val textUri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues) textUri?.let { val outputStream: OutputStream? = resolver.openOutputStream(it) outputStream?.use { it.write("MAS_API_KEY=8767086b9f6f976g-a8df76\n".toByteArray()) it.flush() } Log.d("MediaStore", "File written to external storage successfully.") } ?: run { Log.e("MediaStore", "Error inserting URI to MediaStore.") } } catch (exception: Exception) { Log.e("MediaStore", "Error writing file to URI from MediaStore", exception) } } }路径一:getExternalFilesDir写入应用专属外部目录
mastgTestApi()使用context.getExternalFilesDir(null)获取应用专属外部存储目录,并借助FileOutputStream写入名为secret.txt的明文密码secr3tPa$$W0rd。
该目录在设备上的实际位置形如/sdcard/Android/data/<package-name>/files/(本 Demo 中即/sdcard/Android/data/org.owasp.mastestapp/files/secret.txt)。尽管这类目录被 Android 称为「应用专属」(app-specific),但其位于外部存储上,存在多重风险:
- Android 10(API 29)及以下,具备权限的恶意应用可读取其他应用写入的应用专属外部目录(见 MASTG-KNOW-0042 的说明);
- 启用 USB 大容量存储时,用户可直接修改这些文件;
- 文件在应用卸载时会被删除,但在此之前任何人都可能接触到敏感内容。
知识条目 MASTG-KNOW-0042 给出了同款风险的等价 Kotlin 片段——用context.getExternalFilesDir(null)明文写入password.txt,并明确指出:getExternalStoragePublicDirectory这类 API 返回的是其他应用也能访问的共享位置,属于「Shared Storage Requiring No User Interaction」,具备权限的第三方应用即可读取其中的敏感数据。
路径二:MediaStoreAPI 写入公共下载集合
mastgTestMediaStore()走的是更现代、也更隐蔽的MediaStore路径:
- 构造
ContentValues,指定DISPLAY_NAME(随机文件名secretFile<0..100>.txt)、MIME_TYPE(text/plain)与RELATIVE_PATH(Environment.DIRECTORY_DOWNLOADS,即 Download 公共目录); - 通过
resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)在系统媒体数据库中登记一个新条目,获得content://URI; - 通过
resolver.openOutputStream(uri)向该 URI 写入明文 API Key:MAS_API_KEY=8767086b9f6f976g-a8df76。
从代码结构可以推断,这种写法刻意制造了「检测盲区」:文件不是通过文件路径直接创建的,而是经由 ContentProvider 的抽象层落盘。因此,仅靠对文件路径的静态分析难以发现它,只有动态文件系统快照才能捕获。MediaStore写入的最终落盘位置为/sdcard/Download/secretFile75.txt(见下文output.txt),属于公共共享存储,任何拥有相应权限的应用或直接通过 USB 连接的用户都可读取。
复现步骤:时间戳驱动的文件系统快照
Demo 的检测思路非常朴素却有效:在触发应用行为之前打一个时间戳标记,在之后找出所有「比该标记新」的文件,从而精确锁定本次运行期间应用新创建的文件。这正对应 MASTG-TEST-0200 的核心方法——「在运行应用前后分别获取外部存储文件清单,计算差分」。
完整流程如下:
Step 1:安装应用(可用 MASTG-TECH-0005 描述的安装方式,例如adb install)。
Step 2:执行run_before.sh建立时间基准。脚本内容(run_before.sh):
#!/bin/bash # SUMMARY: This script creates a dummy file to mark a timestamp that we can use later # on to identify files created during the app exercising adb shell "touch /data/local/tmp/test_start"它在设备上创建一个空文件/data/local/tmp/test_start,其修改时间(mtime)即为后续差分的时间基准。
Step 3:打开应用并充分操作。运行mastgTest()触发两条写入路径,让应用真实创建文件。原文档特别强调要「exercise it to trigger file creations」——与 MASTG-TEST-0200 中「尽可能多地触发应用流程、在能输入的地方输入敏感数据」的要求一致,确保敏感数据生成路径全部被执行。
Step 4:执行run_after.sh捕获并拉取新文件。脚本内容(run_after.sh):
#!/bin/bash # SUMMARY: List all files created after the creation date of a file created in run_before adb shell "find /sdcard/ -type f -newer /data/local/tmp/test_start" > output.txt adb shell "rm /data/local/tmp/test_start" mkdir -p new_files while read -r line; do adb pull "$line" ./new_files/ done < output.txt关键点解读:
find /sdcard/ -type f -newer /data/local/tmp/test_start:递归枚举外部存储中所有修改时间晚于时间基准文件的普通文件,结果重定向到output.txt;rm清理时间基准文件(设备端操作,通过adb shell执行);- 逐行读取
output.txt,用adb pull将每个新增文件拉取到本地new_files/目录——这正是 MASTG-TECH-0002(Host-Device Data Transfer) 描述的adb pull <remote> <local>批量取回文件的标准用法,底层由 MASTG-TOOL-0004(adb) 驱动。
Step 5:测试完成后关闭应用,避免后续操作污染后续轮次的快照。
观察结果:清单与明文内容
output.txt记录了应用运行期间新增到外部存储的全部文件(output.txt):
/sdcard/Android/data/org.owasp.mastestapp/files/secret.txt /sdcard/Download/secretFile75.txt两个文件分别印证了上文的两条写入路径:应用专属外部目录中的secret.txt与公共 Download 目录下的secretFile75.txt。
从设备拉回的内容同样一目了然(明文):
new_files/secret.txt:
secr3tPa$$W0rdnew_files/secretFile75.txt:
MAS_API_KEY=8767086b9f6f976g-a8df76一个是应用密码,一个是 API Key——典型的高价值凭据数据。
评估:为什么该测试必然失败
按照 MASTG-TEST-0200 的评估标准:若发现的文件未加密且泄露敏感数据,则测试失败。本 Demo 的判定为:
- 敏感数据成立:
secret.txt含明文密码secr3tPa$$W0rd,secretFile75.txt含明文 API KeyMAS_API_KEY=8767086b9f6f976g-a8df76; - 未加密成立:两个文件均为纯文本明文,无任何加密层;
- 可被他人获取:文件落在外部存储(含公共 Download 目录),攻击面明确。
因此测试失败。原文档还建议通过逆向工程应用并检查代码进一步确认——即回到MastgTest.kt源码,直接看到fileContent与MAS_API_KEY常量,验证明文写入行为。
同时需要注意 MASTG-TEST-0001 给出的 MASVS 合规基线:L1 合规允许数据以明文存放在应用内部存储沙箱中;L2 合规则要求使用 Android KeyStore 安全管理的密钥进行加密(如 DEK+KEK 信封加密,或 Android Security Library 的EncryptedFile/EncryptedSharedPreferences)。外部存储的明文敏感数据在任何等级下都不合规。
底层原理:外部存储为何危险
外部存储的风险根源在于其共享性。结合 MASTG-KNOW-0042 可梳理出以下关键事实:
- 共享属性:外部存储可能是可移除的 SD 卡,也可能是系统模拟的不可移除分区;其中的公共目录对所有应用开放。
- 版本差异(Scoped Storage):Android 10(API 29)起默认启用分区存储(scoped storage),应用默认无法访问其他应用的应用专属目录;但 API 29 及以下版本的应用可通过
android:requestLegacyExternalStorage="true"临时退出分区存储,且 Android 11(API 30)起该属性被系统忽略。 - 权限演进:
READ_EXTERNAL_STORAGE/WRITE_EXTERNAL_STORAGE在 Android 13(API 33)起不再生效,访问媒体集合需改用READ_MEDIA_IMAGES/READ_MEDIA_VIDEO/READ_MEDIA_AUDIO;MANAGE_EXTERNAL_STORAGE(「所有文件访问」)仅适用于 targetSdk 30+,且受 Google Play 政策严格限制。 - 实战攻击面:除恶意应用读取外,还包括「Man-in-the-Disk」类攻击(攻击者替换外部存储中被应用信任的数据文件)以及用户通过 USB 直接导出文件等场景。
因此 Android 官方安全准则的建议是:不要在外部存储存放敏感数据;若必须使用,需对数据做输入校验并配合加密。
加固建议:如何修复该漏洞
针对本 Demo 暴露的问题,修复方向分为两层:
1. 存储位置整改:敏感数据(密码、API Key、Token 等)应优先存入应用内部存储沙箱(/data/data/<package-name>/files/),或在 Android Keystore 中保存;仅将非敏感媒体内容写入外部存储。
2. 强制加密:对必须持久化的敏感数据使用加密存储。EncryptedFile与EncryptedSharedPreferences(androidx.security:security-crypto)是常见方案——虽然该库当前已标记为弃用(官方替代方案尚未发布,MASTG-TEST-0001 建议在替代品发布前继续使用),其核心思想仍是:用 Android Keystore 保护的密钥(KEK)加密数据密钥(DEK),实现信封加密,密钥永不以明文离开安全硬件。
3. 静态分析预防:在代码审查阶段即可拦截此类问题——检查AndroidManifest.xml中的READ/WRITE_EXTERNAL_STORAGE等权限声明,并在源码中检索getExternal*系列函数、FileOutputStream、getExternalFilesDir、MediaStore写入调用等风险 API(完整检索清单见 MASTG-TEST-0001 的 Static Analysis 一节),同时对硬编码密钥、XOR 拼接密钥等弱加密手法保持警惕。
配套资源
- 样本源码:MastgTest.kt
- 快照脚本:run_before.sh / run_after.sh
- 观察产物:output.txt、secret.txt、secretFile75.txt
- 测试标准:MASTG-TEST-0200、MASTG-TEST-0001
- 知识背景:MASTG-KNOW-0042(External Storage)
- 技术工具:MASTG-TECH-0002(Host-Device Data Transfer)、MASTG-TOOL-0004(adb)
- 文档
- 教程
- 网络安全
【免费下载链接】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.
相关推荐
使用 Semgrep 检测 Android 键盘缓存敏感输入:MASTG-DEMO-0064 实战解析
使用 Semgrep 检测 Android 键盘缓存敏感输入:MASTG DEMO 0064 实战解析 MASTG DEMO 0064 是 OWASP MAS
文档教程网络安全shadcn-vue Dropdown Menu 组件完整指南:安装、API 与实战示例
shadcn vue Dropdown Menu 组件完整指南:安装、API 与实战示例 本指南围绕 shadcn vue 中的 Dropdown Menu(下
文档教程网络安全使用 Frooky 检测 Firebase Analytics 敏感用户数据外发:MASTG-DEMO-0081 实战演示
使用 Frooky 检测 Firebase Analytics 敏感用户数据外发:MASTG DEMO 0081 实战演示 导读 本文以 OWASP Mobil
文档教程网络安全
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考