TikTok Android 高危漏洞剖析:一键式账户劫持(CVE-2022-28799)

大家好,我是白帽攻防录的白帽K。今天分享的是TikTok Android 高危漏洞技术。

一、漏洞概述

微软在 TikTok Android 应用程序中发现了一个高危漏洞,攻击者只需让用户点击一次,即可在用户无感知的情况下劫持其账户。该漏洞的利用需要将多个问题串联在一起,目前该漏洞已被修复,微软方面尚未发现任何在野利用的证据

攻击者可以利用该漏洞,在目标用户仅点击一个特制链接的情况下,就悄无声息地劫持其账户。随后,攻击者可以访问并修改用户的 TikTok 个人资料及敏感信息,例如:

  • 公开用户的私密视频
  • 以用户名义发送消息
  • 以用户名义上传视频

该漏洞的核心在于:允许绕过应用内的深度链接(deeplink)校验。攻击者可以强制应用将任意 URL 加载到应用的 WebView 中,从而使该 URL 能够访问 WebView 上附加的 JavaScript 桥接(JavaScript Bridge),并向攻击者授予相应功能。

二、影响范围

TikTok 的 Android 应用有两个版本:

版本包名面向地区
TikTok(东亚/东南亚版)com.ss.android.ugc.trill东亚、东南亚
TikTok(其他地区版)com.zhiliaoapp.musically除印度外的其他地区

两个版本在 Google Play 商店中的累计安装量超过 15 亿次

在对 TikTok 进行漏洞评估时,微软确认这些问题同时影响两个版本的 Android 应用。在仔细评估影响后,微软安全研究人员根据其负责任披露政策,通过微软安全漏洞研究(MSVR)的协调漏洞披露(CVD)机制,于 2022 年 2 月 将问题通报给了 TikTok。TikTok 迅速作出响应,发布了修复补丁,该漏洞现已被标识为 CVE-2022-28799

三、技术原理:JavaScript 接口与桥接

3.1 WebView 与 JavaScript 接口

该漏洞的利用依赖于应用对 JavaScript 接口的实现,这些接口由 Android 操作系统的一个组件——WebView 提供。WebView 允许应用程序加载和显示网页,并通过 addJavascriptInterface API 调用提供桥接功能,使网页中的 JavaScript 代码能够调用应用中某个特定类的 Java 方法。

安全风险:将不受信任的 Web 内容加载到 WebView 中,同时让 JavaScript 代码可以访问应用级别的对象,会使应用面临 JavaScript 接口注入风险,可能导致数据泄露、数据损坏,在某些情况下甚至导致任意代码执行

下面是一个使用 JavaScript 接口的示例代码,JsObject 类的实例被注入到 WebView(第 8 行),并在 JavaScript 代码中通过 injectObject 变量引用,通过 loadUrl API 方法加载(第 10 行):

// 图 1:向 WebView 对象添加 JavaScript 接口
1  class JsObject {
2      @JavascriptInterface
3      public String toString() { return "injectedObject"; }
4  }
5
6  webView.getSettings().setJavaScriptEnabled(true);
7
8  webView.addJavascriptInterface(new JsObject(), "injectedObject");
9
10 webView.loadUrl("file:///android_asset/demo.html");

图1:向 WebView 对象添加 JavaScript 接口

在 Android API 级别 18(2013 年随 Android 4.3 发布)之前,被注入类的任何方法都会暴露给这段 JavaScript 代码。从 API 级别 18 开始,只有带有 @JavascriptInterface 注解(如上第 2 行所示)的类方法才能被调用。

3.2 JavaScript 桥接

TikTok for Android 大量使用 JavaScript 接口,以增强应用内使用的 WebView 能力。研究人员确定了一个使用此类 WebView 的类,它注册了一个 JavaScript 桥接,该桥接可以访问由 [redacted].bridge.* 包中各类实现的全部功能

图2:使方法可被 JavaScript 代码调用

该桥接暴露的方法中,参数 arg1 对应一个 JSON 字符串,其中 funcparams 属性最为关键:

  • func:对应从 JavaScript 代码中调用的 Java 方法名
  • params:设置该方法所接收的参数

例如,要从 JavaScript 代码中调用签名为 String foo(String arg1, String arg2) 的 Java 方法,需使用以下语句:

// 图 3:通过 JavaScript 接口调用 Java 方法
const result = injectObject.call({
    func: "foo",
    params: ["value1", "value2"]
});

图3:通过 JavaScript 接口调用 Java 方法

结果会以 JSON 字符串的形式返回给 JavaScript 代码中定义的回调函数。整体交互流程如下:

  1. 应用程序将网站 example.com 加载到其 WebView 中
  2. 从远程服务器获取的 JavaScript 代码调用 Java 方法
  3. 该方法被执行
  4. 结果作为参数返回给回调函数
  5. handler 方法可在本地处理结果,或使用 XMLHttpRequest 将其发送到外部服务器(攻击中可借此将被盗数据发送到攻击者服务器)

图4:Java 与 Web 组件通过 JavaScript 接口交互

四、漏洞成因:深度链接(Deeplink)校验绕过

4.1 什么是深度链接

在 Android 操作系统中,**深度链接(deeplink)**是一种特殊的超链接,链接到移动应用内的特定组件,由 scheme(协议)和(通常还有)host(主机)部分组成。当用户点击深度链接时,Android 包管理器会查询所有已安装应用,确定哪个应用能处理该链接,然后将其路由到声明为处理者的组件。

若要在应用上下文之外被其他组件使用,深度链接必须在应用的清单文件(Manifest)中声明:

<!-- 图 5:在清单文件中添加 intent filter 进行深度链接 -->
<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="example" android:host="gizmos" />
</intent-filter>

图5:在清单文件中添加 intent filter 进行深度链接

当有多个应用能处理同一个 scheme 时,系统会弹出**歧义对话框(ambiguity dialog)**让用户选择。为了避免 http/https scheme 的歧义对话框,应用可以通过 autoVerify 属性声明 Android 应用链接(App Link),并在 https://domain.name/.well-known/ 目录下发布包含包名及证书 SHA256 指纹的 JSON 文件。TikTok for Android 对 m.tiktok.com 域使用了这一功能。

图6:歧义对话框

内部深度链接:除了清单文件中导出的深度链接,应用还可以用内部深度链接在组件间交换数据。若从应用外部(如浏览器)打开内部深度链接,系统会返回"无法解析 Intent"错误,因为系统无法将其路由到适当处理者。

4.2 漏洞发现

在审查应用对特定深度链接的处理时,研究人员发现了一些问题,这些问题被串联起来后,可以迫使应用将任意 URL 加载到 WebView 中。通过为该 URL 附加额外的查询参数,可以注入一个 JavaScript 桥接实例,从而获得对 [redacted].bridge.* 包所实现功能的完全访问权限

4.3 触发应用的内部深度链接

TikTok for Android 使用了多种深度链接 scheme,其中 https://m.tiktok[.]com/redirect 链接由 [redacted] 类处理,用于通过查询参数将 URI 重定向到应用的各个组件。

研究人员确认:可以通过查询参数触发内部深度链接并调用未导出的 Activity,从而扩大应用的攻击面。

图7:使用 Medusa 识别深度链接及其目标 Activity

作为概念验证,研究人员构造了一个 URL,使用某个特定的未导出 scheme 将 https://www.tiktok[.]com 加载到应用的 WebView(图 8 成功加载);而 Example.com 则被应用过滤器拒绝(图 9),提示"该链接可能不安全"。

图8:链接触发内部 scheme 并加载 Tiktok.com

图9:应用过滤器拒绝加载 Example.com

[redacted-scheme]://webview?url=<website>

过滤是在服务端进行的,加载或拒绝 URL 的决定基于某个特定 HTTP GET 请求的回复。然而,研究人员的静态分析表明,可以通过向深度链接添加两个额外参数来绕过服务端检查

一旦绕过成功,附加到该 Activity 的 WebView 会创建 JavaScript 桥接的实例。从此时起,分配给查询参数的网站对 JavaScript 桥接拥有完全访问权限,可调用 [redacted].bridge.* 包下任何已暴露的功能。

五、已暴露的功能与攻击面

审查加载到 WebView 中的 JavaScript 代码可访问的功能后,研究人员发现了 超过 70 个已暴露的方法。当与劫持 WebView 的漏洞利用相结合时,攻击者可调用这些方法:

  • 访问或修改用户的隐私信息(如私密视频、个人资料设置)
  • 对任意 URL 执行经过身份验证的 HTTP 请求(方法接受 JSON 字符串参数构造 POST 请求正文,并返回服务器回复及响应头)

通过调用这些方法,攻击者可以:

  1. 窃取身份验证令牌——触发对受控服务器的请求,记录 Cookie 和请求头
  2. 检索或修改账户数据——触发对 TikTok 端点的请求,通过 JavaScript 回调获取回复

简而言之,只要控制了任何能够执行经过身份验证的 HTTP 请求的方法,恶意行为者就可能攻陷 TikTok 用户账户。

六、攻击链路:概念验证(PoC)

完整攻击流程如下:

  1. 攻击者向目标 TikTok 用户发送特制链接
  2. 用户点击链接后,攻击者的服务器 https://www.attacker[.]com/poc 获得对 JavaScript 桥接的完全访问权限
  3. 攻击者服务器返回一个包含 JavaScript 代码的 HTML 页面,该代码将视频上传令牌发送回攻击者,并修改用户个人简介
  4. 视频上传的身份验证令牌通过 XMLHttpRequest 发送回攻击者(含请求头与响应头)

图10:攻击获取的请求头

图11:服务器包含响应头的回复

  1. 最终,用户个人简介被修改为 "!! SECURITY BREACH !!!"

图12:用户个人简介被篡改为 "!! SECURITY BREACH !!!"

整个过程中,用户仅需点击一次链接,全程无感知。

七、JavaScript 接口的安全最佳实践

从编程角度来看,使用 JavaScript 接口存在重大风险:被攻陷的 JavaScript 接口可能允许攻击者使用应用的 ID 和权限执行代码。微软建议开发者社区采取以下防护措施:

核心建议

  • 使用受信任域的批准列表(白名单),仅加载白名单内的域到 WebView,防止加载恶意内容
  • 使用默认浏览器打开不属于应用批准列表的 URL
  • 保持批准列表及时更新,并跟踪所包含域的到期日期(防止攻击者认领已过期域名劫持 WebView)
  • 避免使用部分字符串比较方法将 URL 与白名单比对验证
  • 避免将暂存(stage)或内部网络域加入白名单(这些域可能被伪造)

给普通用户的防护建议

  • 避免点击来自不受信任来源的链接
  • 始终保持设备和已安装应用为最新版本
  • 切勿安装来自不受信任来源的应用
  • 立即向厂商报告任何异常应用行为(如无用户交互下的设置更改)

八、总结与思考

本案例展示了 WebView 的 JavaScript 桥接机制在缺乏严格输入校验时可能带来的严重安全风险,以及深度链接校验被绕过后攻击面的急剧扩大。

几个值得关注的技术要点:

  1. JavaScript 接口是一把双刃剑——它在提升 WebView 能力的同时,也将 Java 层的能力暴露给了不可信的前端代码
  2. 服务端校验并非万无一失——通过构造额外参数即可绕过,安全校验应当纵深防御、多道把关
  3. 内部深度链接可被外部触发——扩大了攻击面,需谨慎处理未导出组件的可达性

该漏洞由微软安全研究人员 Dimitrios Valsamaras 发现,微软通过协调漏洞披露(CVD)机制于 2022 年 2 月通报 TikTok。TikTok 在不到一个月内发布了修复版本,漏洞被评定为高危(CVSS 8.3)。这体现了安全社区内跨行业协作在缓解安全威胁中的重要作用。


​​​​在这里插入图片描述

参考来源

免责声明:本文基于微软官方安全报告翻译整理,仅供技术学习与安全研究交流使用。

如果这篇文章对你有帮助,别忘了 👍 点赞、⭐ 收藏、💬 评论三连支持!你的每一次互动都是我持续输出干货的最大动力!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值