M1: Improper Platform Usage
M1: Improper Platform Usage
This category covers misuse of platform features or failure to use platform security controls. It includes violations of published guidelines, misuse of platform permissions, and incorrect usage of platform security features.
Common Examples:
- Misuse of Touch ID/Face ID or Android Biometric API
- Incorrect implementation of Keychain/Keystore
- Improper permission requests
- Violations of platform security guidelines
iOS Implementation Issues and Solutions:
// VULNERABLE: Improper Keychain usage
class VulnerableKeychainManager {
func savePassword(_ password: String, for account: String) {
// Bad: Storing plain text in UserDefaults
UserDefaults.standard.set(password, forKey: account)
// Bad: Using Keychain without proper access control
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account,
kSecValueData as String: password.data(using: .utf8)!,
kSecAttrAccessible as String: kSecAttrAccessibleAlways // Too permissive
]
SecItemAdd(query as CFDictionary, nil)
}
}
// SECURE: Proper Keychain implementation
class SecureKeychainManager {
func savePassword(_ password: String, for account: String) throws {
guard let passwordData = password.data(using: .utf8) else {
throw KeychainError.encodingError
}
// Create proper access control
var error: Unmanaged<CFError>?
guard let accessControl = SecAccessControlCreateWithFlags(
kCFAllocatorDefault,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
[.biometryCurrentSet, .devicePasscode],
&error
) else {
throw error?.takeRetainedValue() ?? KeychainError.accessControlError
}
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account,
kSecAttrService as String: Bundle.main.bundleIdentifier ?? "com.app",
kSecValueData as String: passwordData,
kSecAttrAccessControl as String: accessControl,
kSecAttrSynchronizable as String: false
]
// Delete existing item first
SecItemDelete(query as CFDictionary)
// Add with proper error handling
let status = SecItemAdd(query as CFDictionary, nil)
guard status == errSecSuccess else {
throw KeychainError.saveError(status)
}
}
}
Android Implementation Issues and Solutions:
// VULNERABLE: Improper platform usage
class VulnerableStorageManager(private val context: Context) {
// Bad: Using SharedPreferences for sensitive data
fun saveCredentials(username: String, password: String) {
val prefs = context.getSharedPreferences("user_prefs", Context.MODE_WORLD_READABLE) // Dangerous!
prefs.edit()
.putString("username", username)
.putString("password", password)
.apply()
}
// Bad: Requesting unnecessary permissions
fun requestAllPermissions() {
val permissions = arrayOf(
Manifest.permission.READ_CONTACTS,
Manifest.permission.READ_SMS,
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.ACCESS_FINE_LOCATION
)
// Requesting all permissions at once without justification
}
}
// SECURE: Proper platform usage
class SecureStorageManager(private val context: Context) {
fun saveCredentials(username: String, password: String) {
// Use Android Keystore for key generation
val keyAlias = "user_credentials_key"
val keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES,
"AndroidKeyStore"
)
val keyGenSpec = KeyGenParameterSpec.Builder(
keyAlias,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setUserAuthenticationRequired(true)
.setUserAuthenticationValidityDurationSeconds(300)
.setRandomizedEncryptionRequired(true)
.build()
keyGenerator.init(keyGenSpec)
keyGenerator.generateKey()
// Use EncryptedSharedPreferences
val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.setUserAuthenticationRequired(true)
.build()
val encryptedPrefs = EncryptedSharedPreferences.create(
context,
"secure_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
encryptedPrefs.edit()
.putString("username", username)
.putString("password", password)
.apply()
}
}