FlawOpen

flawopen.com/Android WebView 安全/addJavascriptInterface

Android addJavascriptInterface:风险与安全用法

参考页面
简要结论

应将启用了 addJavascriptInterface 的 WebView 视为特权边界。Android 会把对象注入每个 frame,应用无法判断调用方法的是哪个 frame。如果攻击者控制的 JavaScript 到达任一 frame,就可能以应用权限调用已暴露的方法。启用桥的 WebView 只加载应用控制的内容;不可信页面应在不带该桥的独立 WebView 中加载。

桥接如何改变 XSS 的影响

桥接为 JavaScript 提供可调用的宿主应用入口。Android 会向所有 frame(包括 iframe)暴露该对象,addJavascriptInterface 不会检查调用 frame 的来源。因此,注入的脚本可能调用带注解的桥接方法;其能力取决于这些方法和应用自身的授权检查。对于 target API 为 16 或更低的应用,Android 记录了更严重的旧行为:所有公共方法都可能暴露。从 API 17 起,必须使用 @JavascriptInterface,但该注解不会让不可信内容变得安全。

让桥接远离不可信页面

有风险——桥接与不可信导航共用一个 WebView
webView.addJavascriptInterface(
  NativeBridge(), "Android"
)
webView.loadUrl(untrustedUrl)
更安全——隔离可信与不可信内容
// 此 WebView 仅用于应用控制的内置界面。
trustedWebView.settings.javaScriptEnabled = true
trustedWebView.addJavascriptInterface(
  NativeBridge(), "Android"
)
trustedWebView.loadUrl("file:///android_asset/index.html")

// 另一个 WebView 负责远程或用户可控页面。
untrustedWebView.removeJavascriptInterface("Android")
untrustedWebView.settings.javaScriptEnabled = false
// 同时校验 HTTPS 和明确的主机 allowlist。
untrustedWebView.loadUrl(validatedHttpsUrl)

最可靠的边界来自架构:启用桥接的 WebView 不应导航到远程、用户生成或受攻击者影响的页面。如果必须加载不可信内容,应在加载前移除接口,并使用另一个默认关闭 JavaScript 的 WebView,除非确有需要。Android 指出,注入对象对所有 frame 可见,移除操作要到下一次页面加载后才生效。HTTPS 保护传输,不会让主机或其内容自动可信。校验 URL 的 scheme 和 host,并在系统浏览器中打开不在允许列表中的链接。缩小桥接方法范围、校验每个参数,并在原生代码中实施授权,不要信任调用页面。

Android WebView 桥接安全常见问题

API 17 或更高版本会自动让 addJavascriptInterface 变安全吗?

不会。API 17+ 将暴露范围限制为带 @JavascriptInterface 注解的公共方法;它不会验证调用 frame 的来源,也不会让攻击者控制的内容变可信。桥接只应留在仅加载应用控制内容的 WebView 中。

参考资料

另请参阅 XSS 跨站脚本攻击(CWE-79):原理与各编程语言的防护方法 — flawopen.com Angular XSS 防护:安全默认行为与绕过 API MIME 嗅探 XSS:Content-Type 与 nosniff CSP 与输出转义:两者都需要吗? React 的 dangerouslySetInnerHTML 安全吗? DOMPurify 足以保护 innerHTML 吗? Markdown 渲染能防御 XSS 吗?