本节摘要:单一 HTTPS 挡不住本地明文 Token + 逆向提取密钥的组合拳。本节讲 CIA 三元组、最小权限、安全默认、信任最小化,以及如何在代码/存储/通信/认证/后端五层叠加深度防御——SOURCE 1.4 的核心图表将落实为评审清单。
| 属性 | 移动场景 | 失效信号 |
|---|---|---|
| 机密性 (C) | Token 加密存 Keychain | adb 导出 prefs 可读 |
| 完整性 (I) | 签名校验、防重打包 | 二次打包仍能通过登录 |
| 可用性 (A) | 证书 Pin 误配导致全站不可用 | 换证书后老版本全崩 |
CIA 不是口号:评审时每一类数据都要标注 C/I/A 要求。
CAMERA 若真拍照;Android 11+ 分区存储减少 READ_EXTERNAL_STORAGE
// Android:最小权限 + 安全默认 — 敏感数据不进普通 SharedPreferences val masterKey = MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build() val securePrefs = EncryptedSharedPreferences.create( context, "auth_prefs", masterKey, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM )
iOS 对应:Keychain + kSecAttrAccessibleWhenUnlockedThisDeviceOnly,避免 iCloud 同步 Token。
| 原则 | Android | iOS |
|---|---|---|
| 最小权限 | 运行时权限 + 特性声明 | Info.plist 用途字符串 |
| 安全默认 | Network Security Config | ATS |
| 纵深防御 | SafetyNet/Play Integrity | App Attest / DeviceCheck |
代码混淆(ProGuard/R8、Swift 符号剥离)提高逆向成本,不能替代服务端授权。纵深防御里混淆只属于「代码层」一环。
⚠️ 常见坑:硬编码 AES 密钥再混淆——Frida hook
SecretKeySpec仍可取密钥。
💡 关键直觉:纵深防御 = 攻击者突破一层后,下一层仍有效且可检测。
第 2 章把这些原则映射到 OWASP Mobile Top 10 具体威胁。
纵深防御不是「多设几道门」,而是每一层都能独立扛住攻击、被突破后能被检测。代码层看混淆与完整性校验是否生效,存储层看明文搜索是否为零,通信层看装用户 CA 能否解密,认证层看服务端是否真正裁决,后端层看 API 是否有鉴权与限流。每一层的验证方法不同,把「层、控制、验证手段」列成矩阵,评审与测试都能对照执行。
// 代码层示例:完整性校验失败即退出(示意) if (!integrityOk(signatureDigest)) { // 检测到重打包,拒绝进入业务 finishAffinity() }
信任最小化是移动安全里最反直觉的一条:把 Intent、Deep Link、推送 payload 都当作不可信输入。Deep Link 是高频入口,恶意 App 可以注册相同 scheme 抢收;推送 payload 若被中间人注入,也会触发不安全的跳转。把这些入口列为输入验证重点。
| 层 | 典型控制 | 验证手段 |
|---|---|---|
| 代码 | 混淆+完整性 | Frida 模拟篡改 |
| 存储 | Keystore 加密 | adb 读明文 |
| 通信 | TLS+Pinning | Burp 装用户CA |
| 认证 | 服务端 RBAC | 改包越权测试 |
| 后端 | 鉴权+限流 | 自动化用例 |
最小权限与安全默认是评审里最快出成果的两条原则。逐条核对:Manifest 里每个权限都有功能依据吗;运行时权限拒绝后功能优雅降级吗;Debug 开关在生产包关闭吗;WebView 是否禁用了文件访问与 JS 桥;网络默认是否拒绝明文与未知证书;测试入口是否从生产包剥离。每一项都能在几分钟内验证,却往往是最容易被忽略的修复点。
| 检查项 | 安全默认 | 违例信号 |
|---|---|---|
| 权限声明 | 最小集合 | 无关权限堆积 |
| 调试开关 | 生产关闭 | debuggable=true |
| 网络策略 | 禁明文 | cleartext 允许 |
| WebView | 禁文件+JS桥 | 暴露接口 |
| 测试入口 | 生产剥离 | 隐藏菜单存在 |
纵深防御强调多层,但不等于每层都平均用力。成本上,先保证最容易被利用的层(通信、存储)的基线,再逐步加固代码层;效果上,每一层都要有独立的验证手段,否则「多设的几道门」只是心理安慰。评审时问一个问题:如果攻击者已经绕过第一层,第二层能拦住吗?答不上来,说明该层形同虚设。