🔓 Android 客户端 APK 安全渗透测试指南(小白入门版)
👨💻 一文读懂 Android 客户端的潜在风险与渗透思路,手把手教你做安全检测!
🧭 一、引言:没做过 APK 安全分析?该怎么下手?
如果你从没做过 App 客户端的安全检测,第一次接到 APK 项目时,可能会一脸问号:“我该从哪下手?”、“要查哪些内容?”、“是不是要会逆向?”
别慌,其实大部分 App 的常见安全问题,通过一套固定思路 + 常用工具,就能快速识别和验证。
在本文中,我会用通俗易懂的方式,带你逐步掌握 APK 渗透测试的核心流程,从静态配置检查,到本地存储分析,再到动态调试与通信劫持,手把手教你如何对一个 APK 做完整的安全检测。
📌 本文适合这些读者:
- 想入门 Android 渗透测试的新手
- 有基础但没做过 APK 检测的安全人员
📄 二、AndroidManifest.xml 安全配置排查
AndroidManifest.xml 是 Android App 的“总指挥部”,定义了应用的权限、组件、调试配置等内容,也是安全分析的重要起点。
✅ 2.1 组件导出风险
- 一些组件如
Activity
、Service
、BroadcastReceiver
设置了exported=true
,但没有任何访问控制。 - 攻击者可以直接启动敏感页面或服务,绕过登录验证,构建恶意请求。
- 工具:ADB、Drozer【排查工具 👉 APKDeepLens、MobSF 】
- 命令:
adb shell am start -n <包名>/<完整的Activity名>
🔧 2.2 调试功能未关闭(容易被动态调试)
- Manifest 中的
android:debuggable="true"
允许外部工具连接调试 App。 - 一旦开启,攻击者可以使用 Android Studio 等轻松调试代码、修改逻辑。
- 修复方式:上线前一定要设置为
false
或直接删掉!
🧳 2.3 任意备份功能未禁用(数据轻松被导出)
- 如果设置了
android:allowBackup="true"
(默认就是),用户数据可以被 ADB 一键导出! - 可能泄露 token、密码、用户隐私信息等。
- 修复建议:设为
false
——android:allowBackup="false"
上面这几项,直接在AndroidManifest.xml中搜索则可
🧩 三、组件安全分析
🕹️ 3.1 Activity 暴露分析
- 未鉴权的 Activity,攻击者可以直接跳转过去使用敏感功能。
- 示例:启动支付页面、内嵌 WebView,甚至后台管理功能页面。
- 工具:
adb shell am start -n <包名>/<完整的Activity名>
🚀 3.2 Service 与广播组件滥用
- 导出的 Service 接收者未做鉴权,可能被任意启动或注入恶意 Intent。
- BroadcastReceiver 可能被“广播欺骗”,触发未授权操作。
- 利用 drozer 快速扫描服务入口。
📚 3.3 ContentProvider 数据泄露
- 若 Provider 未加权限限制,可被查询/写入,甚至注入 SQL 语句。
- 示例:通过
content://
路径直接导出用户数据。 - 详情 👉 ContentProvider 数据泄露全面解析:小白也能看懂的安全检测指南-极客星球
🗃️ 四、本地数据存储安全
🔐 4.1 SharedPreferences / 文件 / 数据库存储检查
✅ 1. SharedPreferences
- 后缀名:
.xml
- 存储路径(以包名为
com.example.app
为例): /data/data/com.example.app/shared_prefs/ - 说明:以 XML 格式存储键值对,常用于保存登录状态、token 等敏感信息。检查是否以明文保存。
✅ 2. 文件存储(File)
- 后缀名:不固定,常见如
.txt
、.json
、.log
、.conf
等 - 常见路径:
- 私有目录: /data/data/com.example.app/files/
/data/data/com.example.app/cache/ - 外部存储(SD 卡): /sdcard/Android/data/com.example.app/files/
/sdcard/Android/data/com.example.app/cache/
- 私有目录: /data/data/com.example.app/files/
- 说明:重点检查是否将敏感信息(如账号、密码、加密密钥等)以明文写入本地文件。
✅ 3. 数据库存储(SQLite)
- 后缀名:
.db
(数据库文件),.db-journal
(事务日志) - 存储路径: /data/data/com.example.app/databases/
- 说明:应用数据库,可能包含用户数据、缓存信息、Token 等内容。可用工具如
DB Browser for SQLite
查看内容,关注是否存在明文数据。
✅ 重点:root环境导出APP数据目录或直接用Root Exploer等安卓软件查看上述文件,排查内部是否存在敏感信息则可
✅ 拓展:可结合
jadx
查看读写操作代码(如getSharedPreferences()
、openFileOutput()
、SQLiteOpenHelper
)。
🧮 4.2 加密逻辑是否安全
- 关注加密算法安全性:查看是否使用不安全算法,如 ECB 模式的 AES 或 MD5、SHA1 等弱哈希算法。
- 排查硬编码密钥:检查代码中是否直接写死密钥(通过
jadx
等工具逆向定位常见加密函数如Cipher.getInstance()
或MessageDigest.getInstance()
)。 - 分析重点加密逻辑:对关键签名参数进行跟踪,判断是否采用弱加密方式(如简单的
md5(appid + timestamp)
形式)。 - 动态调试辅助验证:使用
Frida
Hook 加密函数(如encrypt()
,digest()
),可获取明文或中间加密过程,验证逻辑实现。
✅ 重点:检查是否存在 MD5、SHA1、AES-ECB、硬编码密钥等典型弱点,可以使用工具👉 Jadx-GUI。
🍪 4.3 WebView 缓存 / Cookie 泄露风险
✅ WebView 风险说明
- WebView 组件在加载网页时,可能自动保存:
- Cookie(登录态)
- 浏览历史 / 表单数据
- 缓存资源(如 HTML、JS、图片)
- 若未正确清理或加密,攻击者获取设备文件权限后可直接读取,造成隐私或账号信息泄露。
📁 相关数据路径
以下目录通常存储 WebView 相关缓存与数据:
/data/data/<包名>/app_webview/ # Chromium 核心缓存数据
/data/data/<包名>/app_webview/Cookies # Cookie 数据库
/data/data/<包名>/app_webview/Web Data # 自动填充 & 表单数据
/data/data/<包名>/app_webview/Default/Cache # 缓存资源
🔍 检查要点
- Cookie 是否以明文存在,可通过 SQLite 查看
Cookies
数据库。 - 检查是否启用了
setSavePassword(true)
(已被弃用但老版本仍可能使用)。 - 是否使用了
WebView.clearCache()
、clearHistory()
、CookieManager.removeAllCookies()
等清理逻辑。 - 简单来说就是排查上面路径的数据是否包含像Token等敏感数据,如果有是否加密,加密方式是否安全
📄 五、日志打印 / 内存泄露风险
🔍5.1 日志打印排查
💻 使用 adb logcat 实时抓取日志
adb logcat > log.txt
持续运行一段时间,或者执行关键操作后停止。
🔍 搜索敏感关键词
关键词示例:
grep -iE "token|session|password|pwd|auth|access_token|secret|key" log.txt
- 关键词包括:
token
、session
、password
、pwd
、auth
、access_token
、secret
、key
等 - 结合业务可加自定义关键词(如用户名、Token关键词字段)
💾5.2 内存打印排查
🔍 重点查找“静态引用”敏感对象
在反编译后Jadx中直接全局搜索:
// 查找静态持有 Context(可能导致 Activity 无法释放)
static Context
// 查找静态持有 WebView(可能导致泄露)
static WebView
// 查找静态保存 token、session 等敏感信息
static token
static session
static password
static secret
判定方式:
static Context
/static WebView
:属于 Android 最常见的内存泄露隐患(特别是非 Application Context)。- 如果你看到有
static String token = ...
明文保存登录信息,这属于高危,因为这段信息会一直驻留内存。
🔧 Frida 检查动态内存中是否存在敏感字符串
例如使用 Frida 脚本搜索内存中含 token
的字符串:
// 简易内存字符串搜索(Frida)
Java.perform(function () {
Java.choose("java.lang.String", {
onMatch: function (instance) {
var str = instance.toString();
if (str.indexOf("token") !== -1 || str.indexOf("eyJ") === 0) {
console.log("[敏感字符串] " + str);
}
},
onComplete: function () {}
});
});
eyJ
是 JWT Token 的开头 Base64 编码,查找内存字符串中是否包含对应内容
🔧 Android Studio Profiler
- 连接设备,打开 Android Studio → Profiler
- 点击 Memory,录制内存快照
- 搜索关键字如
token
、password
,查看是否存在于对象中
✍️ 六、签名校验与篡改检测
🔏 6.1 签名校验的现状与作用
- Android 应用通过代码校验自身签名,防止被恶意重打包和篡改。
- V2/V3 签名机制从系统层面加强了 APK 的完整性校验,防止静态篡改。
- 即便如此,应用层的签名校验代码依然不可或缺,作为二次防护。
🛠️ 6.2 篡改检测与绕过风险
- 攻击者无法轻易修改带 V2/V3 签名的 APK 并成功安装,但仍可通过动态手段(如 Frida Hook)绕过签名校验代码。
- 静态修改 APK 后重新签名几乎不可能绕过系统完整性校验,除非掌握签名私钥。
- 应用签名校验逻辑若设计不严密,易被绕过,需重点检测其实现及防护能力。
⚠️ 6.3 排查建议
- 静态分析
- 查找签名校验代码(通常在 Application 或登录流程)
- 审计校验逻辑是否严密、是否包含硬编码签名信息
- 动态分析
- 利用 Frida 等工具验证签名校验是否能被绕过
- 部分APK通过签名来防止被Hook和篡改,所以绕过签名校验后,攻击者动态调试将更加方便和隐蔽
- 绕过签名可实现绕过授权限制、篡改运行逻辑、注入恶意代码,导致敏感数据泄露和安全防护失效。
- 结合系统特性
- 关注 APK 使用的签名版本(V1/V2/V3)
- 评估系统层面完整性保护对应用安全的影响
💡 6.4 总结
应用代码签名是指对应用代码进行数字签名以保证代码完整性和来源可信;而 V2/V3 是 Android APK 的具体签名方案,作用是对整个安装包进行整体完整性校验和防篡改,二者概念上属于不同层级,前者泛指代码保护,后者是 APK 签名技术实现。
方面 | 现状与建议 |
---|---|
APK V2/V3 签名 | 静态防篡改效果显著,基本阻断非法重打包 【看见v2/v3重打包就不用试了】 |
应用签名校验代码 | 必须保留且加固,防止动态绕过 |
动态绕过风险 | 依然存在,需结合动态检测和防护 【Frida绕过校验可篡改或访问未授权内容】 |
未来排查方向 | 静态+动态联合,结合系统 新机制持续强化安全防护 |
🌐 七、通信安全分析
📡 7.1 HTTPS 校验与抓包绕过
- 是否真正使用了 HTTPS?是否做了 SSL Pinning?
- 若未启用,抓包可直接看到明文数据。
- 若启用了,可用 Hook 脚本绕过,所以一般APP上线前还要做混淆、加密、加固。
📥 7.2 SSL Pinning常见代码逻辑
- 绑定服务端证书,关键词:
checkServerTrusted
public class SSLTrustManager implements X509TrustManager {
private X509TrustManager delegateTrustManager;
public SSLTrustManager(String certString) {
try {
// 1. 证书工厂,解析 X.509 格式证书
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// 2. 从字符串加载证书
ByteArrayInputStream inputStream = new ByteArrayInputStream(certString.getBytes());
X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
inputStream.close();
// 3. 初始化 KeyStore,导入证书
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setEntry("ca_root", new KeyStore.TrustedCertificateEntry(cert), null);
// 4. 创建 TrustManagerFactory,并用 KeyStore 初始化
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
// 5. 从 TrustManagerFactory 获取 X509TrustManager 委托对象
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
this.delegateTrustManager = (X509TrustManager) tm;
return;
}
}
} catch (Throwable e) {
// 异常处理
}
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// 通常客户端校验留空或简单日志
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// 核心校验逻辑,校验证书有效期等
// 可能会调用 delegateTrustManager.checkServerTrusted()
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return delegateTrustManager.getAcceptedIssuers();
}
}
- 设置可信任的服务端域名,关键词:
HostnameVerifier
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
// 只信任特定的服务器域名
return "api.example.com".equalsIgnoreCase(hostname);
}
});
🌍 7.3 WebView 安全配置
- 是否暴露了不安全的接口(如
addJavascriptInterface
)? - 是否允许 file 协议加载?可能造成本地文件泄露、XSS。
🧪 八、环境与反调试机制分析
🧲 8.1 Root 检测方式分析
- App 可能通过检测 su、magisk、系统属性等判断是否 Root。
- 常见绕过:Frida Hook 检测函数、Magisk 模块隐藏。
🧑💻 8.2 模拟器与虚拟机检测
- 检测 CPU 架构、硬件名、传感器数量、品牌型号等。
- 绕过方式:Xposed 模拟器伪装模块、自定义 patch。
🛡️ 8.3 调试检测与绕过技巧
- 检测函数如
Debug.isDebuggerConnected()
。 - App 若检测到调试器存在,会立刻崩溃或终止功能。
- Frida 可直接 Hook 返回 false,实现绕过。
📌 九、总结与加固建议
- 🧩 漏洞总结:从配置、组件、通信到防护全面覆盖
- 🔐 开发建议:
- 严控组件导出权限
- 禁止调试与备份
- 加强本地数据加密
- 启用 SSL 校验并防抓包
- 🧰 工具推荐:jadx、apktool、Frida、drozer、Burp Suite、MobSF 等
暂无评论内容