Android JSBridge 漏洞分析笔记
基础概念
JSBridge:APP在Webview中给H5页面提供调用Java/Kotlin APP原生代码的桥,例如获取登录态,打开相机/相册,定位/分享/支付等等
Deeplink:通过URI将用户引导到特定页面的链接,决定“打开谁”,示例:myapp://open/mywebview?url=https://www.baidu.com
Webview:APP内嵌的网页渲染组件,可以加载H5页面,决定“怎么展示”
典型实现
可以通过 addJavascriptInterface() 将 Java 对象暴露给网页 JavaScript
1 | public class AppBridge { |
通过 Deeplink 触发的一种典型攻击流程:
- 用户点击来自浏览器,其他APP,扫描二维码得到的恶意链接
- 系统根据Intent及 Intent Filter 等信息匹配APP特定Activity
- APP解析传入 URI 的scheme,host,path,query等组成部分
- 路由模块匹配到WebView加载外部URL
- APP 的 WebView 加载了攻击者可控或存在 XSS 的网页
- 如果该页面能够访问具有敏感能力的 JSBridge,攻击者可调用相应方法
- 根据接口功能和权限校验情况,可能造成敏感信息泄露或未经授权的业务操作
概括:攻击者使可控 JavaScript 在具有桥接能力的 WebView 中执行,由于能调用校验不完善的原生接口,导致用户敏感信息泄露或未经授权的操作
常见场景
1. 任意 URL 加载 + JSBridge 暴露
攻击者通过 Deeplink 控制 WebView URL,使不可信页面获得原生接口调用能力
2. XSS + JSBridge
可信 H5 页面存在 XSS,攻击者注入的 JavaScript 继承该页面可用的桥接能力
3. iframe + JSBridge
addJavascriptInterface() 注册的对象会暴露给包括跨域 iframe,攻击者可控 iframe 中的 JavaScript 因而调用原生接口
真实案例
CVE-2023-41898 in Home Assistant Companion
Home Assistant Companion 是用于连接 Home Assistant 智能家居服务的移动 APP
该 Activity 配置了 android:exported=”true”,并注册了处理 https://my.home-assistant.io/redirect/ 的 Intent Filter
1 | <activity android:name=".launch.my.MyActivity" |
MyActivity.kt 从传入的 Intent 中读取 URL,并在启用 JavaScript 的 WebView 中加载。shouldOverrideUrlLoading() 会识别以 homeassistant://navigate/ 开头的 URL,并将后面的内容传递给 WebViewActivity
1 | if (Intent.ACTION_VIEW == intent?.action && |
WebViewPresenterImpl.onViewReady() 会将传入的 path 交给 UrlUtil.handle() 处理,该工具函数在识别到绝对 HTTP 或 HTTPS URL 时可以直接将输入转换为 URL
1 | fun handle(base: URL?, input: String): URL? { |
在 WebViewActivity.kt 中,APP 还注册了 JavaScript Interface,并提供 getExternalAuth() 等方法,getExternalAuth() 接收 JSON 参数,其中 callback 由 JavaScript 提供,并被传递给 Native 端的认证处理逻辑,Native 代码将这个回调字符串拼接到 JavaScript 代码中,再交由 evaluateJavascript() 执行
1 |
|
CVE-2026-78997 in UC Browser
UC 关联域名 mtmsg.uc.cn 的页面会将 email 参数未经充分转义地写入 HTML,存在XSS漏洞
http://mtmsg.uc.cn/ads_rlink.php?email="%3E%3Cscript%3Ealert(1)%3C/script%3E&action=add
该域名又处于 UC Browser 的白名单范围内,因此注入的 JavaScript 可以访问 ucapi.invoke 等桥接能力
UC Browser 向网页提供内部 JavaScript Bridge
1 | ucapi.invoke("account.openLoginWindow", { |
其中 account.openLoginWindow 用于打开浏览器的原生登录窗口。loginCallback 和 dismissCallback 是由网页提供的 JavaScript 回调字符串。通过反编译发现,Native 端会把这些回调保存到单例对象中,并关联触发调用的 windowID。回调字符串可以在页面导航后继续存在,但没有将回调与注册时的页面来源可靠绑定,导致页面导航后,原先注册的回调仍被保留,并可能在新页面的上下文中执行
1 | // k50/h.java — account.openLoginWindow handler |
回调分发逻辑会把 URL 校验字段设置为空字符串
1 | // m50/a.java — c() — callback dispatcher |
执行器遇到空校验值时,会直接通过 evaluateJavascript() 执行脚本
1 | // com/uc/browser/webwindow/i.java — u3() |
当用户关闭原生登录窗口时,之前注册的回调可以在当前加载的另一个网站上下文中执行
CVE-2026-44698 in Home Assistant Companion
Android Native 端通过 addJavascriptInterface() 注册桥接对象:window.externalApp
其中包括用于获取外部认证信息的 getExternalAuth,以及用于撤销认证的 revokeExternalAuth,
这使前端能够通过 JavaScript 向 Native 发送请求
Android 的 addJavascriptInterface() 会将注册对象暴露给 WebView 中的所有 frame,包括跨域 iframe。
因此如果 Dashboard 中嵌入了第三方网页,该 iframe 自身的 window 中也会暴露 externalApp 对象
Native 处理 getExternalAuth 时,会将 JSON 中的 callback 字段直接插入 JavaScript 字符串,再通过 evaluateJavascript() 执行
由于没有严格限制回调标识符,也没有充分转义,攻击者可以让原本作为回调名称的数据改变 JavaScript 代码的执行逻辑
而 evaluateJavascript() 在主 frame 的 JavaScript 上下文中执行,因此跨域 iframe 可能借此在 Home Assistant 前端的来源下执行代码
修复建议
- 严格解析和校验待加载 URL 的协议、主机,对后续导航和重定向同样设置限制
- 只暴露必要能力,敏感操作独立执行权限校验
- 及时修复白名单域名的 XSS
- 对需要区分来源和主 frame 的桥接,考虑使用 WebViewCompat.addWebMessageListener(),设置严格的 allowedOriginRules,并利用回调中的 sourceOrigin、isMainFrame 实施限制;继续使用 addJavascriptInterface() 时,将第三方内容移至不注册敏感接口的独立 WebView
- 避免把网页提供的回调字符串直接拼接为可执行 JavaScript ,并在页面导航后使旧页面注册的待执行回调失效
参考链接:
https://securitylab.github.com/advisories/GHSL-2023-142_Home_Assistant_Companion_for_Android
https://gist.github.com/OmriInbar-Novee/9fd65fe08c1b1cff6a19350e44425de2
https://github.com/home-assistant/core/security/advisories/GHSA-7jp2-p2fw-mgvf
https://developer.android.com/develop/ui/views/layout/webapps/native-api-access-jsbridge
- 标题: Android JSBridge 漏洞分析笔记
- 作者: j1ya
- 创建于 : 2026-10-17 22:23:43
- 更新于 : 2026-10-17 22:27:08
- 链接: https://redefine.ohevan.com/2026/10/17/Android-JSBridge-漏洞分析笔记/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。