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()
    }
}