Insecure Keychain Storage
Accessibilité Non Sécurisée du Keychain
Description
Le Keychain est une base de données spécialisée pour le stockage sécurisé de données sensibles sur les appareils iOS. Des données telles que des mots de passe, des clés de chiffrement ou des certificats peuvent être enregistrées dans le Keychain.
Lors de la création ou de la mise à jour d'un élément du Keychain, le développeur peut déterminer les conditions dans lesquelles il peut être consulté à l'aide de l'attribut kSecAttrAccessible. L'utilisation de valeurs d'accessibilité faibles comme kSecAttrAccessibleAlways ou kSecAttrAccessibleAlwaysThisDeviceOnly permet d'accéder à l'élément du Keychain même lorsque l'appareil est verrouillé.
kSecAttrAccessibleAlways et kSecAttrAccessibleAlwaysThisDeviceOnly sont obsolètes depuis iOS 12.0 en raison des risques de sécurité. Leur utilisation peut entraîner l'exposition de données sensibles à des personnes non autorisées si l'appareil est perdu, volé ou compromis.
Dans les exemples suivants, une spécification incomplète des indicateurs de contrôle d'accès (SecAccessControlCreateFlags) entraîne un stockage non sécurisé des éléments du keychain :
import Foundation
import Security
func saveSecretToKeychain() {
let secretData = "mySecretPassword".data(using: .utf8)!
let access = SecAccessControlCreateWithFlags(
nil,
kSecAttrAccessibleAlways,
.or,
nil
)
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: "myAccount",
kSecValueData as String: secretData,
kSecAttrAccessControl as String: access!,
]
SecItemAdd(query as CFDictionary, nil)
}
saveSecretToKeychain()
import Foundation
import Security
func saveSecretToKeychain() {
let secretData = "mySecretPassword".data(using: .utf8)!
let access = SecAccessControlCreateWithFlags(
nil,
kSecAttrAccessibleAlways,
.and,
nil
)
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: "myAccount",
kSecValueData as String: secretData,
kSecAttrAccessControl as String: access!,
]
SecItemAdd(query as CFDictionary, nil)
}
saveSecretToKeychain()
Dans ces exemples, il est essentiel de spécifier correctement les indicateurs de contrôle d'accès pour garantir un stockage sécurisé des éléments du keychain. Sans indicateurs spécifiques comme kSecAccessControlUserPresence, les éléments du keychain restent vulnérables à un accès non autorisé.
Recommandation
Lorsque de simples exigences de contrôle d'accès suffisent, vous pouvez spécifier directement le niveau d'accessibilité à l'aide de kSecAttrAccessible. L'omission de kSecAttrAccessControl est acceptable dans ces cas.
| Cas d'utilisation | Protection |
|---|---|
| Stockage de données toujours accessibles | kSecAttrAccessibleAlways |
| Stockage de données accessibles après le premier déverrouillage | kSecAttrAccessibleAfterFirstUnlock |
| Stockage de données accessibles uniquement lorsque l'appareil est déverrouillé | kSecAttrAccessibleWhenUnlocked |
Exemple:
import Foundation
import Security
func saveSecretToKeychain() {
let secretData = "mySecretPassword".data(using: .utf8)!
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: "myAccount",
kSecValueData as String: secretData,
kSecAttrAccessible as String: kSecAttrAccessibleAlways
]
SecItemAdd(query as CFDictionary, nil)
}
saveSecretToKeychain()
Pour des exigences de sécurité plus complexes, telles que l'exigence de la présence de l'utilisateur ou la mise en œuvre de mots de passe spécifiques à l'application, utilisez SecAccessControlCreateWithFlags pour créer un contrôle d'accès avec des indicateurs supplémentaires.
| Cas d'utilisation | Protection | Indicateurs |
|---|---|---|
| Traitement de données sensibles nécessitant la présence de l'utilisateur | kSecAttrAccessibleWhenUnlocked |
kSecAccessControlUserPresence |
| Traitement de données sensibles nécessitant un mot de passe spécifique pour une sécurité accrue | kSecAttrAccessibleWhenPasscodeSet |
kSecAccessControlApplicationPassword |
Exemple:
import Foundation
import Security
func saveSecretToKeychain() {
let secretData = "mySecretPassword".data(using: .utf8)!
let access = SecAccessControlCreateWithFlags(
nil,
kSecAttrAccessibleWhenUnlocked,
kSecAccessControlUserPresence,
nil
)
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: "myAccount",
kSecValueData as String: secretData,
kSecAttrAccessControl as String: access!,
]
SecItemAdd(query as CFDictionary, nil)
}
saveSecretToKeychain()
Liens
- Documentation d'Apple : Restreindre l'accessibilité des éléments du keychain
- Authentification Biométrique Mobile Sécurisée
Normes
- OWASP_MASVS_L2:
- MSTG_AUTH_8
- GDPR:
- ART_5
- ART_25
- ART_32
- PCI_STANDARDS:
- REQ_6_2
- REQ_6_3
- REQ_8_3
- REQ_11_3
- SOC2_CONTROLS:
- CC_2_1
- CC_4_1
- CC_6_1
- CC_7_1
- CC_7_2
- CC_7_4
- CC_7_5
- CNIL_FOR_EDITORS:
- EDITORS_1_3_1
- HIPAA_CONTROLS:
- SECURITY251
- SECURITY212
- SECURITY213