- 文档
- 教程
- 网络安全
【免费下载链接】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 Mobile Application Security Testing Guide(MASTG)最佳实践条目 MASTG-BEST-0011 的完整解读。核心主题是解决 Android WebView 加载本地文件内容时的安全问题:用https://同源加载替代不安全的file://加载,并在不得不使用file://时显式关闭本地文件访问开关。读完本文,你将掌握WebViewAssetLoader的正确用法、三个setAllow*开关在不同 API 级别下的默认值与加固写法,以及如何利用本仓库的测试用例与攻击演示(MASTG-DEMO-0029)验证和审计自己的 WebView 配置。
核心结论:优先用 WebViewAssetLoader + https:// 替代 file://
MASTG-BEST-0011 给出的推荐做法是:使用WebViewClient配合 AndroidX WebKit 提供的WebViewAssetLoader,通过https://URL 加载应用 assets 或 resources 目录下的内容,而不是使用不安全的file://URL。
这样做的收益是:内容在安全、同源的环境中加载,本地文件不会被暴露给潜在的跨源攻击(cross-origin attacks)。典型的配置代码如下:
// Kotlin 示例:使用 WebViewAssetLoader 以 https:// 加载 assets val assetLoader = WebViewAssetLoader.Builder() .addPathHandler("/assets/", WebViewAssetLoader.AssetsPathHandler(context)) .build() webView.webViewClient = object : WebViewClientCompat() { override fun shouldInterceptRequest( view: WebView, request: WebResourceRequest ): WebResourceResponse? { return assetLoader.shouldInterceptRequest(request.url) } } webView.loadUrl("https://appassets.androidplatform.net/assets/index.html")// Java 示例 WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder() .addPathHandler("/assets/", new WebViewAssetLoader.AssetsPathHandler(context)) .build(); webView.setWebViewClient(new WebViewClientCompat() { @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { return assetLoader.shouldInterceptRequest(request.getUrl()); } }); webView.loadUrl("https://appassets.androidplatform.net/assets/index.html");其中https://appassets.androidplatform.net/是WebViewAssetLoader约定的保留域名,shouldInterceptRequest会把对该域名下路径的请求映射到 app 的 assets/resources 目录,页面因此拥有一个真实的 HTTPS 同源 origin,符合标准的同源策略与 CORS 行为。这一"使用保留 HTTPS 域名作为 base URL"的思路在仓库的演示应用中有直接印证:MASTG-DEMO-0097/MastgTestWebView.kt 通过loadDataWithBaseURL("https://appassets.androidplatform.net/assets/support/", ...)为内联 HTML 指定了同样的安全 base URL,使页面脚本运行在非透明的 HTTPS origin 之下。
为什么 file:// 不安全:威胁模型
要理解最佳实践背后的逻辑,需要先明白file://加载的问题所在。根据仓库知识条目 MASTG-KNOW-0018: WebViews 的说明:
- WebView 是嵌入在应用内的浏览器内核(Android 4.4 起基于 Chromium),页面没有地址栏,用户无法直观判断当前加载了何种内容。
- WebView 除了移动应用自身的威胁,还会暴露在常见的 Web 威胁之下(XSS、Open Redirect 等)。
- 一旦 WebView 中加载了任何不可信页面,攻击者注入的脚本就可能尝试利用 WebView 桥接(bridge)或诱导用户。
- 当 app 为 WebView 设置了
WebViewClient后,所有导航都由 WebView 自身处理,任何资源都可能被加载进 WebView —— 这属于最需要防御的配置形态,必须实现 URL 白名单校验。
file://方案的核心风险在于:本地文件页面运行在file://这一特殊 scheme 下,其 origin 通常是null(opaque origin),配合被放宽的文件访问开关,脚本可以绕过同源策略读取本机其他文件,甚至将数据外发到远程服务器。
三个关键开关与默认值速查
MASTG-BEST-0011 与 MASTG-KNOW-0018 明确了三个控制 WebView 本地文件访问的WebSettings方法,其默认值随 API 级别不同而不同。下表汇总(来源:MASTG-KNOW-0018 中的 "WebView Local File Access Settings" 章节):
| API | 作用 | 默认True的 API 级别 | 默认False的 API 级别 | 是否弃用 |
|---|---|---|---|---|
setAllowFileAccess | 允许 WebView 使用file://URL 从本地文件系统加载文件 | <= 29(Android 10) | >= 30(Android 11) | 否 |
setAllowFileAccessFromFileURLs | 允许file://上下文中的 JavaScript 访问其他file://URL | <= 15(Android 4.0.3) | >= 16(Android 4.1) | 是(API level 30 起) |
setAllowUniversalAccessFromFileURLs | 允许file://上下文中的 JavaScript 访问任意来源资源,绕过同源策略 | <= 15(Android 4.0.3) | >= 16(Android 4.1) | 是(API level 30 起) |
需要特别强调的补充点:
- assets 与 resources 不受影响:无论上述开关如何设置,通过
file:///android_asset与file:///android_res访问 assets/resources 始终被允许(见 MASTG-KNOW-0018)。也就是说,只读的打包资源访问不是这些开关的管控范围,真正需要警惕的是对应用内部存储、外部存储文件的访问。 setAllowContentAccess的默认行为不同:它控制 WebView 能否通过content://URL 访问 Content Provider,在所有 Android 版本上默认都是true(Android 4.1/API 16 及以上默认启用),不受minSdkVersion影响。该开关同样应纳入审计范围,详见下文"Content Provider 访问"部分。
逐个 API 详解与代码示例
setAllowFileAccess:本地文件系统访问总开关
setAllowFileAccess决定 WebView 能否用file://scheme 加载本地文件(内部存储、外部存储)。开启后的一个典型(不安全)写法是加载外部存储中的 HTML:
webView.settings.apply { allowFileAccess = true } webView.loadUrl("file:///sdcard/index.html")WebView 通过file://能访问到的是"应用自身有权限读取的任何文件",包括:
- 内部存储:应用自己的内部存储目录;
- 外部存储:
- Android 10 之前:若应用持有
READ_EXTERNAL_STORAGE权限,可访问整个外部存储(SD 卡); - Android 10 起(分区存储):无需特殊权限即可访问应用专属目录;持有
READ_MEDIA_IMAGES等权限可访问整个媒体目录(含其他应用的数据);持有MANAGE_EXTERNAL_STORAGE权限可访问整个外部存储。
- Android 10 之前:若应用持有
setAllowFileAccessFromFileURLs:本地页面之间的互访
该开关允许通过file://加载的本地页面,从其 HTML 或 JavaScript 中访问其他本地资源。需要注意:当allowUniversalAccessFromFileURLs为true时,该设置的值会被忽略(Android 官方文档明确说明这一行为)。
开启后的示例:
webView.settings.apply { allowFileAccess = true allowFileAccessFromFileURLs = true } webView.loadUrl("file:///sdcard/local_page.html")<!-- In local_page.html --> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Local Page</title> </head> <body> <!-- This image is loaded via a file:// URL --> <img src="file:///android_asset/images/logo.png" alt="Logo"> </body> </html>Chromium 官方文档(仓库知识条目引用)提醒:放宽该 origin 规则后,content://与file://开头的 URL 可以通过XMLHttpRequest访问具有相同放宽 origin 的资源,例如file://foo可以向file://bar发起 XHR。开发者必须警惕用户提供的数据不要运行在content://下,否则用户代码可以访问其他应用提供的任意content://URL,造成严重安全问题。此外,无论此开关如何设置,Fetch API 都不允许访问content://与file://URL。
setAllowUniversalAccessFromFileURLs:最危险的开关
该开关允许运行在本地file://页面中的 JavaScript完全绕过同源策略,访问任意来源的资源。开启后,file://页面拥有 scheme 型 origin,可以跨源访问content://、http://、https://等任意资源 —— 其权限远超公开 Web 的 CORS 限制。
webView.settings.apply { javaScriptEnabled = true allowFileAccess = true allowUniversalAccessFromFileURLs = true } webView.loadUrl("file:///android_asset/local_page.html")assets 目录下local_page.html的内容:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Universal Access Demo</title> <script> // This AJAX call fetches data from a remote server despite being loaded via file:// fetch("https://api.example.com/data") .then(response => response.text()) .then(data => document.getElementById("output").innerText = data) .catch(err => console.error(err)); </script> </head> <body> <div id="output">Loading...</div> </body> </html>关于 Cookie 的注意事项(来自 MASTG-KNOW-0018):设置setAllowUniversalAccessFromFileURLs(true)只是让本地file://中的 JavaScript 能发起跨源请求(XHR、Fetch),从而绕过网络请求层面的同源策略,但它并不会授予读取远程网站 Cookie 的能力:
- Cookie 由 WebView 的
CookieManager统一管理,file://origin 无法通过document.cookie读取,且现代站点普遍使用HttpOnly与Secure标志防护; - 跨源请求默认也不携带 Cookie,除非服务器通过
Access-Control-Allow-Origin: *与Access-Control-Allow-Credentials: true等 CORS 头显式允许。
必须使用 file:// 时的加固清单
MASTG-BEST-0011 明确指出:如果应用确实需要 WebView 加载本地file://文件,必须按minSdkVersion分情况加固:
情况一:minSdkVersion对应的默认值本身就是安全的此时应确保以下方法不被调用、保留默认值;或者为保险起见显式设置为false,保证 WebView 不允许本地文件访问:
webView.settings.apply { allowFileAccess = false // setAllowFileAccess(false) allowFileAccessFromFileURLs = false // setAllowFileAccessFromFileURLs(false) allowUniversalAccessFromFileURLs = false // setAllowUniversalAccessFromFileURLs(false) }// Java 等价写法 webView.getSettings().setAllowFileAccess(false); webView.getSettings().setAllowFileAccessFromFileURLs(false); webView.getSettings().setAllowUniversalAccessFromFileURLs(false); webView.getSettings().setAllowContentAccess(false); // 如不需要 content:// 也应关闭情况二:minSdkVersion对应的默认值不安全(较旧的 API 级别)例如minSdkVersion < 30时setAllowFileAccess默认是true;minSdkVersion < 16时另外两个开关默认是true。此时必须显式将上述方法全部设为false,不能依赖默认值。
此外,Android 官方"Things to avoid"(加载本地内容安全指南的反模式章节)还建议:本地 HTML/JS 文件应放在 app 的 assets 目录而非外部存储(外部存储文件对所有人可读写,属不良实践);对loadUrl中的动态参数要严格校验,防止本地文件包含(Local File Inclusion)。
仓库中的验证:测试用例如何判定不安全配置
MASTG 仓库提供了与 MASTG-BEST-0011 直接对应的测试用例,可用于验证与审计。
静态测试:MASTG-TEST-0252(本地文件访问)
MASTG-TEST-0252 检查代码中对WebSettings三个方法的引用:
setAllowFileAccess:允许 WebView 加载内部/外部存储的本地文件;setAllowFileAccessFromFileURLs:允许本地文件中的 JavaScript 访问其他本地文件;setAllowUniversalAccessFromFileURLs:移除跨源限制。注意:无论该设置如何,JavaScript 始终可以向任意源发送数据(如 POST),该开关只影响读取响应数据—— 即便请求失败,数据也已经发出。
该测试的失败判定条件(三条同时满足即判失败):
setJavaScriptEnabled被显式设为true;setAllowFileAccess被显式设为true,或minSdkVersion < 30时未调用(继承默认值true);setAllowFileAccessFromFileURLs或setAllowUniversalAccessFromFileURLs被显式设为true,或minSdkVersion < 16时未调用(继承默认值true)。
测试还特别强调:"缺少对setAllow*方法的引用"同样值得记录,因为那可能意味着应用正在使用默认值,而在某些场景下默认值是不安全的。审计时应尽量找出应用中的每一个 WebView 实例。
当两个 file-URL 开关都保持false时,被攻击页面读取本地文件会失败,logcat中出现 CORS 拦截日志,且攻击者服务器收不到文件内容:
[INFO:CONSOLE(0)] "Access to XMLHttpRequest at 'file:///data/data/org.owasp.mastestapp/files/api-key.txt' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, https, chrome-untrusted.", source: file:/// (0) [INFO:CONSOLE(31)] "File content sent successfully.", source: file:/// (31)[*] Received POST data from 127.0.0.1: Error reading file: 0动态测试:MASTG-TEST-0253(运行时 Hook)
MASTG-TEST-0253 是 MASTG-TEST-0252 的动态对应用例,采用两种 Hook 思路之一:
- 枚举应用中的
WebView实例并列出其配置值; - 或显式 Hook
setJavaScriptEnabled、setAllowFileAccess、setAllowFileAccessFromFileURLs、setAllowUniversalAccessFromFileURLs四个 setter。
观察项要求输出每个 WebView 设置调用的参数值与调用栈(backtrace);随后借助反编译工具(MASTG-TECH-0023 对应流程)结合调用栈定位代码位置,确认:设置是否被显式使用、配置作用到哪个 WebView 实例、该 WebView 是否加载file://内容(如loadUrl("file://...")或以file://为 base URL 的loadDataWithBaseURL),以及攻击者可控的 JavaScript 是否可能在本地文件上下文中执行并外泄数据。
Content Provider 访问:MASTG-TEST-0250 / MASTG-TEST-0251
由于setAllowContentAccess在所有版本默认均为true(不受minSdkVersion影响),MASTG-TEST-0250(静态)与 MASTG-TEST-0251(动态)专门检查 Content Provider 访问。失败判定为以下条件同时成立:
setJavaScriptEnabled显式为true;setAllowContentAccess显式为true或未被调用(继承默认值true);setAllowUniversalAccessFromFileURLs显式为true。
此时 WebView 中的 JavaScript 可以访问:应用自身声明的 Content Provider(即使未导出),以及其他应用导出的 Provider。测试也提醒:setAllowContentAccess为true本身不构成漏洞,但可与其他漏洞组合放大攻击影响;而allowUniversalAccessFromFileURLs是攻击关键,它放宽了默认限制,使file://页面可以访问包括content://在内的任意来源。若该开关未开启,logcat中会出现类似拦截日志:
[INFO:CONSOLE(0)] "Access to XMLHttpRequest at 'content://org.owasp.mastestapp.provider/sensitive.txt' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, https, chrome-untrusted.", source: file:/// (0)历史用例:MASTG-TEST-0032
MASTG-TEST-0032(MSTG-PLATFORM-6,对应 MASVS-PLATFORM-2)是 MASTG V1 时代的 WebView 协议处理器测试,现已弃用,由 MASTG-TEST-0250 ~ 0253 覆盖。其静态分析要点至今仍有参考价值:
- 逐一确认
setAllowContentAccess、setAllowFileAccess、setAllowFileAccessFromFileURLs、setAllowUniversalAccessFromFileURLs的启用情况,并判断其必要性; - 通过
loadUrl定位加载来源:从外部存储加载 HTML 属不良实践(文件所有人可读写),应放在 assets 目录; - 对
loadUrl中的动态参数做操纵性测试,防止本地文件包含; - 建议维护"允许加载的本地/远程页面与协议"白名单,并在启动时校验本地 HTML/JS 文件的校验和、对 JS 做压缩混淆。
攻击场景演示:MASTG-DEMO-0029 的数据外泄
为直观展示不安全配置的后果,仓库提供了可运行的攻击演示 MASTG-DEMO-0029。其核心源码 MastgTestWebView.kt 完整呈现了"敏感文件 + 漏洞配置 + XSS 注入"的攻击链路:
- 应用先把一个敏感文件
api-key.txt写入内部存储(context.filesDir),模拟缓存的凭据或私有数据; - WebView 配置开启
javaScriptEnabled = true与allowUniversalAccessFromFileURLs = true,且刻意不把allowContentAccess设为false(保留默认的true)以展示默认行为; - 通过
loadDataWithBaseURL("file:///", ...)以file://作为 base URL 加载一段被 XSS 注入的 HTML —— 非透明 origin 被替换为file://origin; - 注入的脚本用
XMLHttpRequest经content://org.owasp.mastestapp.fileprovider/internal_files/api-key.txt读取敏感文件,再用fetchPOST 到http://10.0.2.2:5001/receive(模拟攻击者服务器)完成静默外泄。
源码注释明确说明了每个开关的作用:allowUniversalAccessFromFileURLs是攻击成立的关键(不设置时content://请求会被 CORS 拦截,上述 logcat 错误即会复现);而allowContentAccess若不关闭,攻击脚本就能通过 Provider 访问敏感文件。演示的评估结果记录在 evaluation.txt:
setJavaScriptEnabled: True setAllowContentAccess: True setAllowUniversalAccessFromFileURLs: True三个危险配置全部命中,恰好对应 MASTG-TEST-0250 的失败判定条件。这个演示从反面印证了 MASTG-BEST-0011 的价值:只要按最佳实践关闭本地文件访问开关(或改用WebViewAssetLoader的 HTTPS 同源方案),这条攻击链路在第一步就会被切断。
自动化检测:静态规则 mastg-android-webview-allow-local-access.yml
MASTG 还提供可落地的自动化检测规则 rules/mastg-android-webview-allow-local-access.yml。该规则(Semgrep 格式,语言为 Java,严重级别 INFO,关联 MASVS-PLATFORM-2)通过模式匹配捕获以下 WebView 相关调用:
$WEBVIEW.getSettings(...)$SETTINGS.setJavaScriptEnabled($ARG)$SETTINGS.setAllowContentAccess($ARG)$SETTINGS.setAllowFileAccessFromFileURLs($ARG)$SETTINGS.setAllowFileAccess($ARG)$SETTINGS.setAllowUniversalAccessFromFileURLs($ARG)
规则命中后给出提示 "Detected WebView settings.",配合上述测试用例即可进一步人工评估参数值与攻击可达性。把该规则接入 CI 或配合静态逆向(如对 MASTG-DEMO-0029 的反编译产物 运行),可以快速定位仓库或目标应用中所有值得人工复核的 WebView 配置点。
落地清单与总结
按 MASTG-BEST-0011 落地 WebView 本地内容加载安全,可按以下顺序自查:
- 首选方案:用
WebViewClient+WebViewAssetLoader将 assets/resources 以https://appassets.androidplatform.net/...同源加载,彻底规避file://; - 必须用
file://时:确认minSdkVersion对应的默认值;对setAllowFileAccess、setAllowFileAccessFromFileURLs、setAllowUniversalAccessFromFileURLs显式设false(尤其当minSdk < 30或minSdk < 16时不可依赖默认值); - 评估
setAllowContentAccess:它默认全版本为true,若业务不需要content://,显式关闭;若需要,确认应用自身 Provider 的导出与敏感数据情况; - 结合源码审计:找出应用内每个 WebView 实例与其
WebSettings配置,注意"未调用setAllow*"也可能意味着继承了不安全的默认值; - 动态验证:Hook 四个 setter 观察运行时参数与调用栈(对应 MASTG-TEST-0251/0253),并以 MASTG-DEMO-0029 为攻击样例验证防护是否生效;
- 自动化兜底:接入 rules/mastg-android-webview-allow-local-access.yml 规则扫描可疑配置。
深入阅读可继续查看仓库中的 MASTG-KNOW-0018 知识条目(含本地文件访问设置、Content Provider 访问、WebView 存储与清理、JavaScript 桥接等完整背景),以及对应测试用例 MASTG-TEST-0250、MASTG-TEST-0251、MASTG-TEST-0252、MASTG-TEST-0253。
- 文档
- 教程
- 网络安全
【免费下载链接】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-BEST-0012:Android WebView 中 JavaScript 的安全启用与禁用策略
OWASP MASTG 最佳实践 MASTG BEST 0012:Android WebView 中 JavaScript 的安全启用与禁用策略 开启 Java
文档教程网络安全OWASP MASTG Android 最佳实践:在生产构建中禁用 WebView 调试(MASTG-BEST-0008 深度解析)
OWASP MASTG Android 最佳实践:在生产构建中禁用 WebView 调试(MASTG BEST 0008 深度解析) 本文基于 OWASP MA
文档教程网络安全Bluebird `new Promise` 构造函数完全指南:用法、执行契约与源码级原理
Bluebird new Promise 构造函数完全指南:用法、执行契约与源码级原理 new Promise 是 Bluebird 中创建 Promise 实
文档教程网络安全
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考