JSBridge 是混合开发 App 的"海关"
混合开发 App(原生壳 + H5 核心页面)里,所有 native 能力和 H5 逻辑的交互都走 JSBridge:H5 调 native 算签名、native 给 H5 推登录态、H5 调 native 起支付……把 JSBridge 看光,混合 App 就没有秘密。
JSBridge 有两种主流实现,分析前先分清对手用哪种。
实现一:addJavascriptInterface(直接调用型)
native 把 Java 对象暴露给 JS:
webView.addJavascriptInterface(new BridgeObject(), "NativeBridge");
class BridgeObject {
@JavascriptInterface
public String getSign(String data) { // H5 里 window.NativeBridge.getSign(data) 直接调
return SignUtils.md5(data + SALT);
}
}H5 侧调用是同步的:window.NativeBridge.getSign("xxx") 直接拿到返回值。
分析方法:Frida hook addJavascriptInterface 拿 bridge 名和类名,然后 hook 这个类的所有 @JavascriptInterface 方法,输入输出全透明(前文 WebView 监控篇有完整脚本)。
实现二:URL 拦截型(伪协议)
H5 通过跳转伪协议 URL 发消息,native 在 WebViewClient 里拦截:
// H5 侧
location.href = 'jsbridge://getSign?data=xxx&callback=cb_123';
// 或 iframe.src = ...(解决 location 跳转的副作用)// native 侧
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("jsbridge://")) {
handleBridge(url); // 解析方法名和参数
return true; // 拦截,不真正跳转
}
return super.shouldOverrideUrlLoading(view, url);
}返回值通过 evaluateJavascript("cb_123(result)") 回调给 H5——异步的。
分析方法:hook shouldOverrideUrlLoading 看 H5→native 方向,hook evaluateJavascript/loadUrl("javascript:...") 看 native→H5 回调方向。
精髓一:协议格式逆向
URL 拦截型的 bridge URL 就是一套私有协议,把它当协议文档来逆:
jsbridge://module/action?param1=v1¶m2=v2&callback=cb_xxx收集一批真实调用,整理出方法清单:
| URL 模式 | 功能 | 参数 | 回调数据 |
|---|---|---|---|
jsbridge://security/getSign | 签名 | data, timestamp | sign 字符串 |
jsbridge://device/getInfo | 设备信息 | 无 | json |
jsbridge://pay/start | 支付 | orderId, amount | 支付结果码 |
这张表就是混合 App 的"API 文档",比逆 Java 代码快得多。
精髓二:签名逻辑的"借鸡生蛋"
发现签名走 bridge(H5 调 native 算签名)后,最优雅的利用方式不是逆算法,而是注入 JS 直接调:
// Frida 里拿到 WebView 实例,注入 JS 调用 bridge
Java.perform(function() {
Java.choose('android.webkit.WebView', {
onMatch: function(wv) {
wv.evaluateJavascript(
"window.NativeBridge.getSign('test_data')",
null
);
},
onComplete: function() {}
});
});对 URL 拦截型,注入 location.href='jsbridge://...' 并 hook 回调函数拿结果。配合 HTTP 服务包装,就是一个"签名即服务"——H5 的签名逻辑原封不动为你所用。
精髓三:bridge 的安全问题即逆向入口
很多 bridge 实现有安全缺陷,这些缺陷恰恰是逆向的捷径:
- 方法未鉴权:bridge 方法对任何加载的 H5 可用——你可以让自己的页面调它的签名方法
- 参数未校验:
jsbridge://file/read?path=/data/data/...这类文件操作 bridge 可能能读私有目录(cookie、token 文件) - 回调注入:callback 名拼接进 JS 执行,构造特殊 callback 名可注入任意 JS
审计 bridge 时把这些当 checklist,经常有意外的洞。
总结
- 分清两种实现:addJavascriptInterface(同步直调)vs URL 拦截(异步回调)
- 前者 hook 方法,后者 hook shouldOverrideUrlLoading + evaluateJavascript
- bridge 调用清单就是混合 App 的 API 文档
- 签名走 bridge 时,注入 JS 直调比逆算法优雅得多
交流微信:run1255