使用 SharedPreferences
在 Android 上对敏感信息进行明文存储¶
ID: java/android/cleartext-storage-shared-prefs
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
SharedPreferences
是一个 Android API,它使用简单的数据值集存储应用程序首选项。它使您可以轻松保存、更改和检索存储在用户个人资料中的值。但是,不应以明文形式保存敏感信息。否则,任何进程或植根设备中的用户都可以访问它,或者可以通过链接的漏洞(如通过公开组件意外访问私有存储)来公开它。
建议¶
使用 EncryptedSharedPreferences
API 或其他加密算法来存储敏感信息。
示例¶
在第一个示例中,敏感用户信息以明文形式存储。
在第二个和第三个示例中,代码在将敏感信息保存到设备之前对其进行加密。
public void testSetSharedPrefs(Context context, String name, String password)
{
{
// BAD - sensitive information saved in cleartext.
SharedPreferences sharedPrefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE);
Editor editor = sharedPrefs.edit();
editor.putString("name", name);
editor.putString("password", password);
editor.commit();
}
{
// GOOD - save sensitive information encrypted with a custom method.
SharedPreferences sharedPrefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE);
Editor editor = sharedPrefs.edit();
editor.putString("name", encrypt(name));
editor.putString("password", encrypt(password));
editor.commit();
}
{
// GOOD - sensitive information saved using the built-in `EncryptedSharedPreferences` class in androidx.
MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build();
SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(
context,
"secret_shared_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("name", name);
editor.putString("password", password);
editor.commit();
}
}
private static String encrypt(String cleartext) throws Exception {
// Use an encryption or hashing algorithm in real world. The demo below just returns its
// 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 开发人员:更安全地使用数据
ProAndroidDev:Android 中的加密首选项
常见弱点枚举:CWE-312。