在 Android 上使用本地数据库明文存储敏感信息¶
ID: java/android/cleartext-storage-database
Kind: problem
Security severity: 7.5
Severity: warning
Precision: medium
Tags:
- security
- external/cwe/cwe-312
Query suites:
- java-security-extended.qls
- java-security-and-quality.qls
SQLite 是一种轻量级数据库引擎,通常用于 Android 设备中存储数据。默认情况下,SQLite 本身不提供任何加密机制,并以明文形式存储所有数据,如果敏感数据(如凭据、身份验证令牌或个人身份信息 (PII))直接存储在 SQLite 数据库中,则会带来风险。在已 root 的设备中,任何进程或用户都可以访问这些信息,或者可以通过链接漏洞泄露这些信息,例如通过暴露的组件意外访问私有存储。
建议¶
使用 SQLCipher
或类似库为 SQLite 添加加密功能。或者,在将敏感数据存储到数据库之前,使用加密安全的算法对其进行加密。
示例¶
在第一个示例中,敏感用户信息以明文形式存储。
在第二个和第三个示例中,代码在将敏感信息保存到数据库之前对其进行加密。
public void sqliteStorageUnsafe(Context ctx, String name, String password) {
// BAD - sensitive information saved in cleartext.
SQLiteDatabase db = ctx.openOrCreateDatabase("test", Context.MODE_PRIVATE, null);
db.execSQL("INSERT INTO users VALUES (?, ?)", new String[] {name, password});
}
public void sqliteStorageSafe(Context ctx, String name, String password) {
// GOOD - sensitive information encrypted with a custom method.
SQLiteDatabase db = ctx.openOrCreateDatabase("test", Context.MODE_PRIVATE, null);
db.execSQL("INSERT INTO users VALUES (?, ?)", new String[] {name, encrypt(password)});
}
public void sqlCipherStorageSafe(String name, String password, String databasePassword) {
// GOOD - sensitive information saved using SQLCipher.
net.sqlcipher.database.SQLiteDatabase db =
net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase("test", databasePassword, null);
db.execSQL("INSERT INTO users VALUES (?, ?)", new String[] {name, password});
}
private static String encrypt(String cleartext) {
// Use an encryption or strong hashing algorithm in the real world.
// The example below just returns a SHA-256 hash.
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(cleartext.getBytes(StandardCharsets.UTF_8));
String encoded = Base64.getEncoder().encodeToString(hash);
return encoded;
}
参考¶
Android 开发者:更安全地处理数据
SQLCipher:Android 应用程序集成
常见弱点枚举:CWE-312。