题目
移动应用中如何安全存储用户的敏感数据(如登录凭证)?
信息
- 类型:问答
- 难度:⭐⭐
考点
安全存储机制,敏感数据保护,加密算法应用
快速回答
安全存储敏感数据的关键策略:
- 优先使用系统安全存储:Android使用EncryptedSharedPreferences/KeyStore,iOS使用Keychain
- 避免明文存储:绝对禁止直接写入SharedPreferences或UserDefaults
- 加密敏感数据:使用AES-GCM等强加密算法,密钥由硬件安全模块管理
- 最小化存储原则:仅存储必要数据,及时清除过期凭证
- 防范物理攻击:启用生物认证绑定,防止设备丢失导致的数据泄露
核心原则
移动端敏感数据存储需遵循:机密性(加密存储)、完整性(防篡改)、访问控制(生物认证绑定)。
平台特定实现
Android最佳实践
// 使用EncryptedSharedPreferences(API 23+)
val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
EncryptedSharedPreferences.create(
context,
"secret_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
).edit().apply {
putString("auth_token", encryptedToken)
apply()
}原理说明:密钥通过KeyStore保护,使用TEE安全环境执行加解密操作。
iOS最佳实践
// 使用Keychain + 生物认证
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: "userAuthToken",
kSecValueData as String: token.data(using: .utf8)!,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
kSecUseAuthenticationUI as String: kSecUseAuthenticationUIAllow,
kSecAccessControl as String: SecAccessControlCreateWithFlags(
nil,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
.biometryCurrentSet,
nil)!
]
SecItemAdd(query as CFDictionary, nil)原理说明:数据加密存储在安全飞地(Secure Enclave),访问需通过FaceID/TouchID验证。
常见错误与风险
- 硬编码密钥:将加密密钥写在代码中(可通过反编译获取)
- 使用弱加密:如ECB模式或自定义加密算法
- 不当的存储位置:存储在SQLite/Realm数据库未加密或外部存储
- 忽略设备绑定:未设置
kSecAttrAccessibleWhenUnlockedThisDeviceOnly(iOS)或setUserAuthenticationRequired(true)(Android)
扩展知识
- 密钥轮换策略:定期更新加密密钥(但需处理旧数据迁移)
- 白盒加密:针对高安全场景(如金融APP),防御运行环境被破解
- 证书锁定(Certificate Pinning):防止网络层中间人攻击获取传输中的敏感数据
- OWASP MASVS标准:要求敏感数据必须通过平台安全API存储(MASVS-STORAGE-2)
验证方法
使用工具检查安全漏洞:
- Android:adb shell查看/data/data/{package}/shared_prefs/
- iOS:Xcode设备控制台检查Keychain项
- 通用:MobSF动态分析或Frida注入测试