Sécurité dans les applications iOS

Bonjour, Habr! Je vous présente la traduction d'un article sur les principes de base de la sécurité des données confidentielles dans les applications iOS «Application Security Musts for every iOS App» par Arlind Aliu.

La sécurité des applications est l'un des aspects les plus importants du développement logiciel. Les utilisateurs d'applications espèrent que les informations qu'ils fournissent sont protégées en toute sécurité. Par conséquent, vous ne pouvez pas simplement donner à quelqu'un des informations confidentielles.

Heureusement, dans cet article, nous discuterons des erreurs que les développeurs font dans leurs applications, ainsi que des moyens de les résoudre.
Suite sous la coupe.

Stockage de données au mauvais endroit


J'ai mené une étude sur plusieurs applications de l'AppStore et beaucoup font la même erreur: les informations confidentielles sont stockées là où elles ne devraient pas être.
Si vous stockez des données personnelles dans UserDefaults , vous les mettez en danger. Les UserDefaults sont stockés dans un fichier avec une liste de propriétés, qui se trouve dans le dossier "Settings" de votre application. Les données sont stockées dans l'application sans la moindre touche de cryptage.

En installant un programme tiers sur mac, comme iMazing, vous n'avez même pas besoin de pirater le téléphone, mais voyez immédiatement toutes les données UserDefaults de l'application installée depuis l'AppStore. Ces programmes vous permettent de regarder et de gérer les données des applications installées sur l'iPhone. Vous pouvez facilement obtenir les UserDefaults de n'importe quelle application.
C'est la principale raison pour laquelle j'ai décidé d'écrire un article - j'ai trouvé un tas d'applications dans l'AppStore qui stockent des données dans UserDefaults , telles que: jetons, abonnements actifs et renouvelables, le montant d'argent disponible, etc. Toutes ces données peuvent être facilement obtenues et utilisées à des fins malveillantes, de la gestion des abonnements payants dans l'application au piratage au niveau du réseau et pire encore.

Et maintenant sur la façon de stocker des données.

N'oubliez pas que seule une petite quantité d'informations doit être stockée dans UserDefaults , comme les paramètres de l'application, c'est-à-dire des données qui ne sont pas confidentielles pour l'utilisateur.

Utilisez les services de sécurité dédiés d'Apple pour stocker des informations personnelles. Le service API de trousseau vous permet de stocker une certaine quantité de données utilisateur dans une base de données cryptée. Vous pouvez y stocker des mots de passe et d'autres données importantes pour l'utilisateur, telles que des informations de carte de crédit ou même de petites notes importantes.
Il peut également y avoir des clés et des certificats chiffrés avec lesquels vous travaillez.

Service API de porte-clés


L'exemple suivant montre comment enregistrer le mot de passe d'un utilisateur dans le trousseau.

class KeychainService { func save(_ password: String, for account: String) { let password = password.data(using: String.Encoding.utf8)! let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: account, kSecValueData as String: password] let status = SecItemAdd(query as CFDictionary, nil) guard status == errSecSuccess else { return print("save error") } } 

Partie du dictionnaire kSecClass: kSecClassGenericPassword signifie que les informations qui doivent être chiffrées sont le mot de passe. Ensuite, nous ajoutons le nouveau mot de passe au trousseau en appelant la méthode SecItemAdd . La récupération des données d'un bundle est similaire à l'enregistrement.

 func retrivePassword(for account: String) -> String? { let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: account, kSecMatchLimit as String: kSecMatchLimitOne, kSecReturnData as String: kCFBooleanTrue] var retrivedData: AnyObject? = nil let _ = SecItemCopyMatching(query as CFDictionary, &retrivedData) guard let data = retrivedData as? Data else {return nil} return String(data: data, encoding: String.Encoding.utf8) } 

Écrivons une petite vérification sur l'exactitude de l'enregistrement et de la réception des données.

 func testPaswordRetrive() { let password = "123456" let account = "User" keyChainService.save(password, for: account) XCTAssertEqual(keyChainService.retrivePassword(for: account), password) } 

À première vue, il peut sembler que l'API du trousseau est assez difficile à utiliser, surtout si vous devez enregistrer plusieurs mots de passe, je vous invite donc à utiliser le modèle de façade à ces fins. Il vous permettra d'enregistrer et de modifier des données en fonction des besoins de l'application.

Si vous souhaitez en savoir plus sur ce modèle, ainsi que sur la façon de créer un wrapper simple pour des sous-systèmes complexes, cet article vous aidera. Internet regorge également de bibliothèques ouvertes qui aident à utiliser l'API Keychain, par exemple SAMKeychain et SwiftKeychainWrapper .

Enregistrement et autorisation de mot de passe


Dans ma carrière de développement, je suis constamment confronté au même problème. Les développeurs stockent les mots de passe dans l'application ou créent une demande au serveur, qui envoie directement le nom d'utilisateur et le mot de passe.

Si vous stockez des données dans UserDefault , après avoir lu les informations de la première partie de l'article, vous comprenez déjà combien vous risquez. En stockant les mots de passe dans le trousseau, vous augmentez considérablement le niveau de sécurité de votre application, mais encore une fois, avant d'enregistrer des informations confidentielles n'importe où, vous devez d'abord les crypter.

Supposons qu'un pirate puisse nous attaquer via notre réseau. Ainsi, il recevra des mots de passe sous forme de texte brut. Il est bien sûr préférable de hacher tous les mots de passe.

Cryptage des données personnelles


Le hachage peut sembler un peu écrasant si vous le faites vous-même, donc dans cet article, nous utiliserons la bibliothèque CryptoSwift . Il a collecté de nombreux algorithmes de chiffrement fiables standard utilisés dans Swift.

Essayons d'enregistrer et de récupérer le mot de passe du trousseau en utilisant les algorithmes CryptoSwift .

 func saveEncryptedPassword(_ password: String, for account: String) { let salt = Array("salty".utf8) let key = try! HKDF(password: Array(password.utf8), salt: salt, variant: .sha256).calculate().toHexString() keychainService.save(key, for: account) } 

La fonction ci-dessus enregistre le nom d'utilisateur et le mot de passe et les enregistre dans le trousseau sous forme de chaîne cryptée.

Voyons ce qui se passe à l'intérieur:

- Le login et le mot de passe sont écrits dans la variable salt sous forme de chaîne
- sha256 remplit le hachage SHA-2
- HKDF est une fonction de génération de clé ( KDF ) basée sur le code d'authentification de message ( HMAC )

Nous avons créé la variable salt afin de compliquer la tâche des hackers. Nous ne pouvions que chiffrer le mot de passe, mais dans ce cas, l'attaquant peut avoir une liste des mots de passe les plus fréquemment utilisés, il les chiffrera sans problème et les comparera avec notre mot de passe chiffré. Ensuite, trouver le mot de passe pour un compte spécifique n'est pas difficile.
Maintenant, nous pouvons nous connecter en utilisant notre compte et la clé générée.

 authManager.login(key, user) 

Bien sûr, le serveur doit savoir ce qui est chiffré dans notre variable salt. Le backend pourra comparer les clés en utilisant le même algorithme pour identifier l'utilisateur.
L'utilisation de cette approche améliorera considérablement la sécurité de votre application.

Comme achèvement


Ne négligez jamais la sécurité de votre application. Dans cet article, nous avons tout d'abord compris quelles pourraient être les conséquences lors du stockage de données sensibles dans UserDefaults et pourquoi le trousseau est nécessaire.

Dans la deuxième partie, nous parlerons d'un niveau de sécurité plus sérieux, chiffrant les données avant de les enregistrer, et discuterons également de la façon de transférer correctement les informations avec les données personnelles vers le serveur.

Source: https://habr.com/ru/post/fr430532/


All Articles