Insecure password storage
不安全的密码存储
描述
密码存储不安全可能导致帐户受损。该漏洞是由于使用容易受到未经授权的访问或妥协的不安全方法存储密码造成的。
以下示例显示了在 Cookie 中不安全地存储密码凭证:
response.addCookie(new Cookie("password", password));
建议
为了安全地存储帐户凭证,请考虑以下建议:
- 对于 Android,使用
AccountManager存储帐户凭证。 - 对于 iOS,使用
keychain存储帐户凭证。
import android.accounts.Account
import android.accounts.AccountManager
import android.content.Context
fun saveCredentials(context: Context, accountType: String, username: String, password: String) {
val accountManager = AccountManager.get(context)
val account = Account(username, accountType)
accountManager.addAccountExplicitly(account, password, null)
}
fun getCredentials(context: Context, accountType: String, username: String): String? {
val accountManager = AccountManager.get(context)
val accounts = accountManager.getAccountsByType(accountType)
for (account in accounts) {
if (account.name == username) {
return accountManager.getPassword(account)
}
}
return null
}
import Foundation
func saveCredentials(username: String, password: String) {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: username,
kSecValueData as String: password.data(using: .utf8)!,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked
]
SecItemDelete(query as CFDictionary)
SecItemAdd(query as CFDictionary, nil)
}
func getCredentials(username: String) -> String? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: username,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]
var dataTypeRef: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)
guard status == errSecSuccess, let data = dataTypeRef as? Data else {
return nil
}
return String(data: data, encoding: .utf8)
}
import 'package:flutter/services.dart';
class CredentialService {
static const platform = MethodChannel('credentialChannel');
static Future<void> saveCredentials(String username, String password) async {
try {
await platform.invokeMethod('saveCredentials', {'username': username, 'password': password});
} on PlatformException catch (e) {
print("Failed to save credentials: '${e.message}'.");
}
}
static Future<String?> getCredentials(String username) async {
try {
return await platform.invokeMethod('getCredentials', {'username': username});
} on PlatformException catch (e) {
print("Failed to get credentials: '${e.message}'.");
return null;
}
}
}
链接
- OWASP Insecure Cryptographic Storage
- OWASP Insecure Data Storage
- CWE-522 Insufficiently Protected Credentials
- CWE-312 Cleartext Storage of Sensitive Information
- CWE-256 Plaintext Storage of a Password
标准
- OWASP_MASVS_L1:
- MSTG_STORAGE_2
- OWASP_MASVS_L2:
- MSTG_STORAGE_2
- PCI_STANDARDS:
- REQ_2_2
- REQ_3_6
- REQ_3_7
- REQ_6_2
- OWASP_MASVS_v2_1:
- MASVS_STORAGE_1
- MASVS_STORAGE_2
- SOC2_CONTROLS:
- CC_2_1
- CC_4_1
- CC_6_7
- CC_7_1
- CC_7_2
- CC_7_4
- CC_7_5
- CNIL_FOR_DEVELOPERS:
- DEVELOPERS_4_1_2
- HIPAA_CONTROLS:
- SECURITY251
- SECURITY212
- SECURITY213