Android STS(Security Test Suite)完整介绍与测试流程
目录
- [STS 概述](#STS 概述)
- [STS 与其他测试套件对比](#STS 与其他测试套件对比)
- [STS 架构设计](#STS 架构设计)
- [STS 测试类型](#STS 测试类型)
- [STS 测试前提条件](#STS 测试前提条件)
- [STS 环境搭建完整流程](#STS 环境搭建完整流程)
- [STS 测试命令大全](#STS 测试命令大全)
- [STS 测试执行流程](#STS 测试执行流程)
- [STS 测试报告解读](#STS 测试报告解读)
- [STS 常见问题与踩坑指南](#STS 常见问题与踩坑指南)
- [STS SecurityTestCase API 参考](#STS SecurityTestCase API 参考)
- [附录:STS 源码结构](#附录:STS 源码结构)
1. STS 概述

1.1 什么是 STS?
STS(Security Test Suite,安全测试套件) 是 Google 推出的 Android 安全专项测试套件,专门用于验证 Android 设备安全补丁的安装情况 和系统安全漏洞。
| 属性 | 内容 |
|---|---|
| 全称 | Android Security Test Suite |
| 首次发布 | 2018 年 8 月 |
| 归属 | Android 兼容性测试体系(XTS: x Test Suite) |
| 目的 | 验证安全补丁、检测内核漏洞、评估系统安全等级 |
| 更新频率 | 每月更新(与月度安全公告同步) |
| 测试版本要求 | 必须使用 Userdebug ROM |
| Root 要求 | 需要 Root 权限(adb root) |
1.2 STS 与 Security Patch 的关系
Google 月度安全公告 (Android Security Bulletin)
│
├── 每月发布新的 CVE 漏洞修复补丁
│
└── STS 套件同步更新对应的安全测试用例
│
├── 验证补丁是否真正生效
├── 检测是否有已修复 CVE 的回归
└── 内核层安全检测(指针泄露、权限提升等)
关键规则 :设备的 ro.build.version.security_patch 日期必须在 3 个月内,否则 GTS 测试会直接失败,设备无法通过 Google 认证。
1.3 STS 在 EDLA 认证中的位置
EDLA 设备认证测试体系
│
├── CTS (兼容性测试) --- 验证 API 符合性
├── GTS (Google 服务测试) --- 验证 GMS 功能
├── VTS (供应商测试) --- 验证 HAL/内核
├── GSI (通用系统镜像测试) --- 验证系统兼容性
├── STS (安全测试) ★ --- 验证安全补丁/漏洞
├── BTS (固件扫描) --- 查权限/签名
└── CheckList --- 新特性检查
2. STS 与其他测试套件对比
| 对比维度 | CTS | GTS | VTS | GSI | STS |
|---|---|---|---|---|---|
| ROM 类型 | User | User | User | User | Userdebug |
| 是否需要 Google IMG | 否 | 否 | 是 | 是 | 否 |
| 是否需要媒体包 | 是 | 是 | 否 | 是 | 否 |
| 单台耗时 | ~170h | ~20h | ~45h | ~35h | ~6-7h |
| 模块数 | ~1055 | ~273 | ~643 | ~347 | ~20 |
| 更新频率 | 季度 | 季度 | 季度 | 月(system.img) | 每月 |
| 核心目的 | API 兼容性 | GMS 功能 | HAL 符合性 | 系统兼容 | 安全补丁 |
STS 最大特点:
- 唯一需要 Userdebug 版本的测试套件
- 唯一不需要额外烧录 Google IMG 和推送媒体包的测试套件
- 模块最少(20个),耗时最短(7小时),但通过要求最严格
3. STS 架构设计
3.1 STS 框架层次结构
STS 基于 Trade Federation (TF) 测试框架构建,形成 5 层继承体系:
java.lang.Object
└─ com.android.tradefed.testtype.junit4.BaseHostJUnit4Test
│ ↓ 提供 JUnit4 测试基础设施
└─ com.android.compatibility.common.tradefed.testtype.BusinessLogicHostTestBase
│ ↓ 添加兼容性业务逻辑
└─ com.android.compatibility.common.tradefed.testtype.ExtraBusinessLogicHostTestBase
│ ↓ 扩展业务逻辑支持
└─ com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase
│ ↓ STS 专用扩展
└─ com.android.sts.common.tradefed.testtype.SecurityTestCase ★
3.2 SecurityTestCase --- 所有 STS 测试的基类
package com.android.sts.common.tradefed.testtype;
public class SecurityTestCase extends StsExtraBusinessLogicHostTestBase {
// 默认超时: 60 秒
protected static final int TIMEOUT_DEFAULT = 60;
// 非确定性操作超时: 315 秒
public static final int TIMEOUT_NONDETERMINISTIC = 315;
// PoC 推送工具
protected PocPusher pocPusher;
// 测试名称
protected TestName testName;
// ──────────── 核心方法 ────────────
// 内核指针泄露检测(最重要)
public void assertNotKernelPointer(
Callable<String> getPtrFunction,
ITestDevice deviceToReboot
);
// 生命周期
protected void setUp(); // 等待设备上线 + 标记启动时间
protected void tearDown(); // 检查崩溃 + 确保联网
protected void safeReboot();
// 网络检测
public void assertWifiConnected(ITestDevice device);
// Mainline 模块检查
public boolean moduleIsPlayManaged(String moduleName);
}
3.3 两种测试模式
SecurityTestCase (抽象基类)
│
├── RootSecurityTestCase ← 需要 Root 权限
│ ├── 内核漏洞检测 (CVE PoC)
│ ├── 权限提升测试
│ └── 底层安全检测
│
└── NonRootSecurityTestCase ← 不需要 Root 权限
├── 应用层安全检测
├── 网络安全测试
└── 权限模型验证
使用建议 :官方文档明确指出,测试用例必须 继承 RootSecurityTestCase 或 NonRootSecurityTestCase,不应直接继承 SecurityTestCase。
4. STS 测试类型
4.1 测试分类
| 分类 | 测试内容 | 示例 |
|---|---|---|
| 内核安全 | 内核指针泄露、驱动漏洞 | CVE-2023-xxxx PoC 验证 |
| 权限安全 | 权限提升、SELinux 违规 | 绕过权限检查的测试 |
| 网络协议安全 | Wi-Fi 加密、蓝牙配对漏洞 | Wi-Fi WPA3 降级攻击检测 |
| 应用安全 | 签名验证、反编译保护 | 签名绕过测试 |
| 加密安全 | TLS 版本、密钥长度 | 弱加密算法检测 |
| 硬件安全 | NFC/UWB 安全、安全元件 | NFC relay attack |
4.2 测试模块示例
| 模块名 | 覆盖内容 | 版本要求 |
|---|---|---|
CtsSecurityBulletinHostTestCases |
安全公告 CVE 补丁验证 | Userdebug |
CtsSecurityTestCases |
通用安全测试 | Userdebug |
StsHostTestCases |
STS 主机端测试 | Userdebug |
StsKernelSecurityTestCases |
内核安全专项 | Userdebug (Root) |
5. STS 测试前提条件
5.1 设备要求
| 检查项 | 要求 | 验证命令 |
|---|---|---|
| ROM 版本 | Userdebug(非 User) | adb shell getprop ro.build.type → userdebug |
| Root 权限 | 必须可用 | adb root → 成功 |
| USB 调试 | 已开启 | adb devices → device |
| 屏幕常亮 | 已开启(Stay Awake) | 开发者选项中开启 |
| USB 安装提示 | 已关闭 | 开发者选项 → 关闭"通过 USB 验证应用" |
| 网络 | VPN 连接(下载 STS 和运行测试时) | 确保网络通畅 |
5.2 安全补丁检查
# 检查 system 分区安全补丁日期
adb shell getprop ro.build.version.security_patch
# 示例输出: 2026-05-05
# 检查 vendor 分区安全补丁日期
adb shell getprop ro.vendor.build.security_patch
# 示例输出: 2026-05-05
要求:两个补丁日期必须一致且在 3 个月内。
6. STS 环境搭建完整流程
6.1 Step 1 --- 下载 STS 测试套件
下载地址 (需 VPN): https://drive.google.com/drive/folders/1xqPTtC6MWiQizfFVdG7Ho0f2oGsmH0e-
选择与设备 SPL(安全补丁级别)月份对应的版本:
android-sts-16-sts-r47-linux-arm64.zip ← 最新版本
android-sts-16-sts-r44-linux-arm64.zip ← 历史版本
...
解压密码 : sts
# 解压
unzip android-sts-16-sts-r47-linux-arm64.zip
# 进入工具目录
cd android-sts/tools
6.2 Step 2 --- 首次运行(预期失败)
./sts-tradefed
# 进入 STS 控制台后
run sts-dynamic-incremental CtsSecurityBulletinHostTestCases
预期结果:报错,提示缺少环境。这是正常的!需要进行以下配置。
6.3 Step 3 --- 配置 Frida 环境
3.1 下载 frida-inject
STS 报错信息中会包含 frida 下载链接,类似:
https://github.com/frida/frida/releases/download/17.6.2/frida-inject-17.6.2-android-arm64.xz
复制链接到浏览器即可下载。
3.2 放置文件并命名
将文件放到 android-sts/testcases/ 目录下,必须命名为:
frida-inject-version-android-arm64
⚠️ 关键踩坑点:
| 问题 | 错误做法 | 正确做法 |
|---|---|---|
| 命名 | frida-inject-17.6.2-android-arm64 |
frida-inject-version-android-arm64(字面量 version) |
| 文件类型 | 归档文件(双击解压后重命名) | 可执行文件 |
| 权限 | 默认 644(不可执行) | chmod 644 或 chmod 777 |
# 进入 testcases 目录
cd android-sts/testcases
# 如果有归档文件问题,双击解压后重命名可执行文件
mv 解压出的文件 frida-inject-version-android-arm64
# 赋予可执行权限
chmod 644 frida-inject-version-android-arm64
# 或批量赋权
chmod 777 *
6.4 Step 4 --- 配置 Ghidra 环境
4.1 下载 Ghidra
根据 STS 报错提示下载对应版本的 Ghidra ZIP 文件:
ghidra_12.0.1_PUBLIC_20260114.zip
4.2 放置文件(关键踩坑)
必须将 ZIP 文件放到以下精确路径:
/tmp/tradefed_ghidra/ghidra_12.0.1_PUBLIC_20260114.zip
⚠️ 关键问题 :ghidra_12.0.1_PUBLIC_20260114.zip 在这个路径中是一个文件夹的名称 (Linux 允许文件夹名包含 .),而非文件。
# 正确做法
sudo mkdir -p /tmp/tradefed_ghidra/"ghidra_12.0.1_PUBLIC_20260114.zip"
sudo cp ghidra_12.0.1_PUBLIC_20260114.zip /tmp/tradefed_ghidra/"ghidra_12.0.1_PUBLIC_20260114.zip"/
# 错误做法(文件直接放 tradefed_ghidra 下)
cp ghidra_12.0.1_PUBLIC_20260114.zip /tmp/tradefed_ghidra/
/tmp 是 Linux 系统临时目录,与 /home 同级,属于用户目录的上上级目录。
/
├── tmp/
│ └── tradefed_ghidra/
│ └── ghidra_12.0.1_PUBLIC_20260114.zip/ ← 文件夹名
│ └── ghidra_12.0.1_PUBLIC_20260114.zip ← 实际文件
├── home/
│ └── user/
└── ...
STS 运行时会自动解析和解压这个 ZIP 文件,无需手动干预。
6.5 Step 5 --- 环境验证
# 再次运行测试验证环境
./sts-tradefed
run sts-dynamic-incremental CtsSecurityBulletinHostTestCases
如果没有新的环境报错,说明环境配置完成,可以正式开始测试。
7. STS 测试命令大全
7.1 基础命令格式
# 增量测试 (MR 版本推荐)
sts-tradefed run sts-dynamic-incremental [-m 模块名] [-t 测试名]
# 全量测试 (IR 版本推荐)
sts-tradefed run sts-dynamic-full [-m 模块名] [-t 测试名]
7.2 常用命令示例
# ═══════════ 全量测试 ═══════════
# 默认全量
sts-tradefed run sts-dynamic-full
# 指定单台设备
sts-tradefed run sts-dynamic-full -s <设备SN号>
# ═══════════ 增量测试 ═══════════
# 指定模块
sts-tradefed run sts-dynamic-incremental -m CtsSecurityTestCases
# 指定模块 + 单项
sts-tradefed run sts-dynamic-incremental \
-m CtsSecurityTestCases \
-t android.security.cts.DynamicPermissionsTest
# 指定具体 Test Case
sts-tradefed run sts-dynamic-incremental CtsSecurityBulletinHostTestCases
# ═══════════ 多设备并行 ═══════════
# 3台设备并行全量测试
sts-tradefed run sts-dynamic-full \
--shard-count 3 \
-s STS00000001 \
-s STS00000002 \
-s STS00000003
# ═══════════ 重试 ═══════════
# 基于第1个测试报告重试
sts-tradefed run retry -r 1
# 多设备重试
sts-tradefed run retry -r 1 \
--shard-count 3 \
-s STS00000001 \
-s STS00000002
7.3 STS 控制台命令
进入 sts-tradefed 控制台后可用:
| 命令 | 功能 |
|---|---|
l i |
列出相关信息 |
l d |
列出已连接设备 |
l r |
列出测试结果 |
l c |
列出配置 |
help |
查看帮助 |
help add |
查看子计划使用方式 |
exit / quit |
退出控制台 |
7.4 版本选择策略
| 场景 | 推荐命令 | 说明 |
|---|---|---|
| MR 版本(小迭代) | sts-dynamic-incremental |
增量模式,只测变更相关项 |
| IR 版本(大版本/首次) | sts-dynamic-full |
全量模式,完整测试 |
| 单项复测 | -m xxx -t xxx |
定位具体失败项 |
8. STS 测试执行流程
8.1 完整测试流程
Step 1: 刷机准备
├── 刷写 Userdebug ROM
├── 开启 USB 调试
├── 开启 Stay Awake (屏幕常亮)
├── 关闭 "Verify apps over USB"
└── 确认 adb root 可用
Step 2: 环境搭建
├── 下载 STS 套件 (对应 SPL 月份)
├── 解压 (密码: sts)
├── 配置 frida-inject
└── 配置 Ghidra
Step 3: 安全补丁检查
├── getprop ro.build.version.security_patch
├── getprop ro.vendor.build.security_patch
└── 确认日期一致且在 3 个月内
Step 4: 执行测试
├── 进入 android-sts/tools/
├── 启动 sts-tradefed
├── 执行测试命令
└── 等待 6-7 小时
Step 5: 结果分析
├── 查看控制台输出
├── 打开 HTML 测试报告
└── 分析 Failed 项
Step 6: 问题修复
├── 查看 logs/ 目录详细日志
├── 定位失败原因
├── 修复系统代码
└── 重新测试
8.2 测试生命周期
设备连接
│
▼
┌──────────────────────────────────────┐
│ setUp() │
│ ├── 等待设备上线 (waitForDeviceOnline)│
│ └── 标记内核启动时间 │
└──────────────┬───────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ 测试执行 │
│ ├── 推送 PoC 代码到设备 │
│ ├── 执行漏洞检测 │
│ ├── 收集内核指针/日志 │
│ └── 断言验证 │
└──────────────┬───────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ tearDown() │
│ ├── 检查设备是否崩溃 │
│ ├── 确保 Wi-Fi 网络连接 │
│ └── 清理测试环境 │
└──────────────────────────────────────┘
9. STS 测试报告解读
9.1 报告位置
android-sts/results/latest/
├── test_result.xml ← XML 详细结果
├── test_result.html ← HTML 可读报告
└── logs/ ← 设备日志
└── <设备SN>/
├── logcat.txt
├── kernel.log
└── ...
9.2 结果状态说明
| 状态 | 含义 | 处理方式 |
|---|---|---|
| Passed ✅ | 测试通过 | 无需处理 |
| Failed ❌ | 测试失败 | 必须修复,否则认证不通过 |
| Skipped ⏭️ | 已跳过(环境不满足) | 检查设备版本/权限 |
| Assumption Failure | 前置条件不满足 | 检查设备配置 |
9.3 HTML 报告示例解读
┌─────────────────────────────────────────────────┐
│ STS Test Report │
│ Date: 2026-06-11 14:30:00 │
│ Device: QDM117 (userdebug) │
│ Security Patch: 2026-05-05 │
├─────────────────────────────────────────────────┤
│ Summary: │
│ ├── Total: 85 │
│ ├── Passed: 80 ✅ │
│ ├── Failed: 2 ❌ │
│ └── Skipped: 3 ⏭️ │
├─────────────────────────────────────────────────┤
│ Failed Tests: │
│ ├── CVE-2023-40113: 内核指针泄露未修复 │
│ └── CVE-2024-0015: 权限提升漏洞存在 │
└─────────────────────────────────────────────────┘
9.4 关键日志位置
# STS 运行日志
android-sts/logs/
# 设备端 logcat
adb logcat -d > device_logcat.txt
# 内核日志
adb shell dmesg > kernel_log.txt
# 崩溃日志
adb shell ls /data/tombstones/
10. STS 常见问题与踩坑指南
10.1 环境配置类
| 问题 | 原因 | 解决方案 |
|---|---|---|
| frida 文件命名错误 | 使用了具体版本号 | 必须用字面量 version 即 frida-inject-version-android-arm64 |
| frida 不可执行 | 文件类型为"归档文件" | 双击解压后重命名 |
| frida 权限不足 | 默认无执行权限 | chmod 644 或 chmod 777 |
| Ghidra 找不到 | 路径不对 | 检查 /tmp/tradefed_ghidra/ghidra_XXX.zip 是否是文件夹 |
| STS 下载慢 | Google Drive 限速 | 使用 VPN + 稳定网络 |
10.2 测试执行类
| 问题 | 原因 | 解决方案 |
|---|---|---|
adb root 失败 |
User 版本 ROM | 必须刷 Userdebug ROM |
run sts 命令无效 |
命令格式错误 | 使用 sts-dynamic-incremental 或 sts-dynamic-full |
| 增量测试退化为全量 | User 版本无法生成基线 | 使用 Userdebug 版本 |
| 测试耗时过长 | 网络不稳定 | 确保 VPN 稳定,关闭不必要的后台应用 |
| 设备在测试中重启 | 内核崩溃或 watchdog 触发 | 检查 /data/tombstones/ |
10.3 版本兼容类
| 问题 | 说明 |
|---|---|
| STS 版本与 SPL 不匹配 | STS 每月更新,必须使用与设备 SPL 月份对应的版本 |
| Android 版本不匹配 | 13-sts 用于 Android 13,16-sts 用于 Android 16 |
| r 版本差异 | r47 > r44,取最新的可用版本 |
11. STS SecurityTestCase API 参考
11.1 常量定义
| 常量 | 类型 | 值 | 说明 |
|---|---|---|---|
TIMEOUT_DEFAULT |
int |
60 | 默认超时(秒) |
TIMEOUT_NONDETERMINISTIC |
int |
315 | 非确定性操作超时(秒) |
11.2 断言方法
| 方法 | 功能 |
|---|---|
assertMatches(pattern, input) |
断言输入匹配正则模式 |
assertMatchesMultiLine(pattern, input) |
多行模式匹配 |
assertNotMatches(pattern, input) |
断言输入不匹配 |
assertNotMatchesMultiLine(pattern, input) |
多行不匹配 |
assertNotKernelPointer(getPtrFunction, device) |
内核指针泄露检测(最重要) |
assertWifiConnected(device) |
断言 Wi-Fi 已连接(含轮询等待) |
assumeIsSupportedNfcDevice(device) |
假设设备支持 NFC |
11.3 工具方法
| 方法 | 返回类型 | 功能 |
|---|---|---|
buildMetricsReportLog(device) |
MetricsReportLog |
构建指标报告 |
createWifiHelper() |
WifiHelper |
创建 Wi-Fi 辅助工具 |
getAbi(device) |
IAbi |
获取设备 ABI |
getBuildInfo(device) |
IBuildInfo |
获取构建信息 |
getPocPusher(device) |
PocPusher |
获取 PoC 推送工具 |
moduleIsPlayManaged(name) |
boolean |
检查模块是否由 Play 管理 |
11.4 Mainline 模块跳过示例
@Test
public void testPocCVE_2023_40113() throws Exception {
// 如果 captiveportallogin 模块由 Play 管理,跳过此测试
assumeFalse(moduleIsPlayManaged(
"com.google.android.captiveportallogin"
));
// 获取 PoC 推送工具
PocPusher pusher = getPocPusher(getDevice());
// 推送并执行 PoC
pusher.pushFile("CVE-2023-40113", "/data/local/tmp/poc");
getDevice().executeShellCommand("/data/local/tmp/poc");
// 验证内核指针未泄露
assertNotKernelPointer(() -> {
return getDevice().executeShellCommand("cat /proc/kallsyms | head -1");
}, getDevice());
}
11.5 生命周期方法
| 方法 | 阶段 | 操作 |
|---|---|---|
setUp() |
Before | 等待设备上线,标记内核启动时间 |
tearDown() |
After | 检查设备崩溃,确保网络连接 |
safeReboot() |
Utility | 安全重启设备 |
updateKernelStartTime() |
Utility | 更新内核启动时间(重启后调用) |
12. 附录:STS 源码结构
12.1 STS 在 AOSP 中的位置
platform/
└── cts/
└── tests/
└── sts/
├── common/
│ └── src/com/android/sts/common/
│ └── tradefed/testtype/
│ ├── SecurityTestCase.java ← 基类
│ ├── RootSecurityTestCase.java ← Root 测试基类
│ ├── NonRootSecurityTestCase.java ← 非 Root 测试基类
│ └── StsExtraBusinessLogicHostTestBase.java
│
├── hostsidetests/
│ ├── securitybulletin/ ← 安全公告 CVE 验证
│ ├── kernel/ ← 内核安全测试
│ ├── networking/ ← 网络安全测试
│ └── permissions/ ← 权限安全测试
│
└── tools/
└── sts-tradefed ← STS 命令行入口
12.2 STS 版本命名规则
android-sts-{Android版本}-sts-r{修订号}-linux-arm64.zip
│ │ │ │
│ │ │ └── 架构 (arm/arm64/x86)
│ │ └── 平台 (linux/windows/mac)
│ │
│ └── Sts 修订版本号 (r43, r44, r47...)
│
└── 对应 Android 版本 (13, 14, 15, 16...)
版本选择规则:
| Android 版本 | STS 套件前缀 | 示例 |
|---|---|---|
| Android 13 | android-sts-13 |
android-sts-13_sts-r22 |
| Android 14 | android-sts-14 |
android-sts-14_sts-r35 |
| Android 16 | android-sts-16 |
android-sts-16_sts-r47 |
总结
| 维度 | 关键要点 |
|---|---|
| 什么是 STS | Google 安全测试套件,验证 Android 设备安全补丁和漏洞修复 |
| 核心要求 | Userdebug ROM + Root 权限 + VPN 网络 |
| 环境依赖 | frida-inject + Ghidra(按报错提示下载配置) |
| 测试模式 | sts-dynamic-incremental(增量)/ sts-dynamic-full(全量) |
| 测试耗时 | 单台约 6-7 小时(约 20 个模块) |
| 更新频率 | 每月更新(与安全公告同步) |
| 通过标准 | 所有用例 Passed,Security Patch 在 3 个月内 |
| 架构 | 5 层继承体系,基于 Trade Federation 框架 |
| 核心 API | SecurityTestCase.assertNotKernelPointer() --- 内核指针泄露检测 |