La sécurité des applications React Native

Par adjemaoune, 22 mars, 2024
Image React Native

Introduction 

Souvent négligée lors du développement d'applications, la sécurité représente un défi majeur. Cette dernière est un aspect essentiel à prendre en compte pour protéger les données sensibles des utilisateurs et garantir l'intégrité de l'application. Bien qu'il soit impossible de créer un logiciel totalement inviolable, la probabilité d'une attaque malveillante ou d'une faille de sécurité diminue proportionnellement à l'effort investi dans la protection de l'application. 

Malgré la vulnérabilité inhérente, en tant que développeur, nous avons la responsabilité de mettre en place les moyens nécessaires afin d’établir une sécurité efficace dans nos applications.

Dans les lignes qui suivent, nous allons découvrir les meilleures pratiques en matière de stockage d’informations sensibles, d’authentification, de sécurité réseau qui nous aideront à mieux protéger notre application et nos utilisateurs.

Stockage d’informations sensibles 

Il est fortement déconseillé pour un développeur de stocker les clés API sensibles dans le code de l’application. Il est à noter que tout ce qui est inclus dans le code est accessible en texte brut à toute personne inspectant l’ensemble de l’application. 

En React Native, des outils sont mis à disposition tels que React-native-dotenv et React-native-config afin d’ajouter des variables spécifiques à l’environnement telles que les points de terminaison de l’API. 

Concernant la clé API qui permet d’accéder à une ressource de l’application, le moyen le plus sûr pour gérer cela serait de créer une couche d'orchestration entre votre application et la ressource. Il peut s'agir d'une fonction sans serveur (par exemple en utilisant AWS Lambda ou Google Cloud Functions) qui peut transmettre la demande avec la clé API requise. Les consommateurs d'API ne peuvent donc point accéder aux secrets du code côté serveur de la même manière que les secrets du code de l’application en question.

En ce qui est des données utilisateur persistantes, il est recommandé de choisir leur stockage en fonction de leur sensibilité. À mesure que l'application est utilisée, il peut être nécessaire de sauvegarder certaines données sur l’appareil afin de prendre en compte l’utilisation hors ligne, minimiser les requêtes réseau ou encore conserver le jeton d’accès de l’utilisateur entre les sessions.   

Async Storage

En React Native, Async Storage est un système de stockage clé-valeur, asynchrone, non-chiffré et persistant qui n’est pas partagé entre les applications. Il s’agit de l’équivalent du stockage local du web. Voici ses cas d’utilisation :

Image retirée.

Stockage Sécurisé

iOS - Keychain Services

Pour la plateforme IOS, Keychain Services offre la possibilité de stocker de manière sécurisée les informations sensibles pour l'utilisateur. Il s’agit d’un emplacement approprié pour conserver des certificats, des jetons, des mots de passe, ainsi que toute autre donnée délicate qui ne devrait pas être intégrée au stockage asynchrone.

Android - Secure Shared Preferences

Shared Preferences stocke un ensemble de données clé-valeur. Ces données ne sont pas chiffrées par défaut. En revanche, Encrypted Shared Preferences encapsule la classe Preferences pour Android et les chiffres automatiquement. 

Android – Keystore

Le système Android Keystore vous permet de stocker les clés cryptographiques dans un conteneur pour rendre plus difficile leur extraction depuis l'appareil.

Pour intégrer ces services dans votre application, vous avez deux options : écrire un pont personnalisé vous-même ou utiliser une bibliothèque qui encapsule ces fonctionnalités, en fournissant une API unifiée, Voici quelques bibliothèques à prendre en considération :

  • expo-secure-store
  • react-native-encrypted-storage – utilise Keychain sur IOS et EncryptedSharedPreferences sur Android.
  • react-native-keychain
  • react-native-sensitive-info

L’authentification et les liens profonds

Image retirée.

Contrairement au web, les applications mobiles présentent une vulnérabilité particulière : les liens profons ou «Deep Linking» en anglais. Ces liens sont un moyen de transmettre des données directement à une application native depuis une source externe. Un lien profond possède la forme app:// suivi de l'emplacement de votre schéma d'application, et tout ce qui suit le // peut être utilisé en interne pour traiter la demande.

Pour mieux illustrer le contexte, prenons l’exemple d’une application de commerce électronique. On utiliserait app://products/1 comme lien profond vers notre application afin d'ouvrir la page de détails du produit pour le produit portant l'identifiant 1

 En d’autres termes, les liens profonds ne sont pas sécurisés, car qu’il n’existe pas de méthode centralisée d’enregistrement des schémas d’URL. Donc, le développeur ne doit jamais y envoyer des informations sensibles.  

Le risque potentiel réside dans le fait qu'une application malveillante puisse potentiellement détourner le même schéma choisi par le développeur et accéder ainsi aux données de son lien. 

Bien que l'envoi de liens tels que app://produits/1 ne soit généralement pas dangereux, transmettre des jetons représente un problème de sécurité majeur.

 

OAuth2 et les redirections

Image retirée.

Considéré comme le protocole le plus complet et le plus sécurisé du marché, Le protocole d'authentification OAuth2 est incroyablement populaire de nos jours. Son système se base sur la logique où l'utilisateur est invité à s'authentifier via un tiers. En cas de réussite, ce tiers le redirige vers l'application demandée avec un code de vérification qui peut être échangé contre un JWT - JSON Web Token, un standard ouvert pour la transmission sécurisée d'informations en ligne.

Sur le web, cette redirection est sécurisée grâce à l'unicité des URL. Cependant, les applications mobiles ne bénéficient point de cette garantie. Pour remédier à ce problème, une couche de sécurité supplémentaire, appelée Proof of Key Code Exchange (PKCE), est ajoutée à OAuth2. PKCE utilise l'algorithme de hachage cryptographique SHA-256 pour créer une vérification que les demandes d'authentification et d'échange de jetons proviennent du même client.

Le processus PKCE implique la génération d'une chaîne aléatoire (code_verifier) par le client, dont le SHA-256 (code_challenge) est envoyé avec la demande d'autorisation. Une fois la demande autorisée, le client renvoie le code_verifier initial, et l'IDP vérifie que le code_challenge correspond à celui défini lors de la demande initiale, avant d'émettre le jeton d'accès. Ainsi, seule l'application initiatrice du flux d'autorisation peut échanger avec succès le code de vérification, renforçant la sécurité contre les applications malveillantes. 

Pour intégrer OAuth2 avec le support PKCE dans une application mobile React Native, la bibliothèque React-native-app-auth est fortement recommandée, car elle inclut les bibliothèques natives AppAuth-iOS et AppAuth-Android. L’image ci-dessous démontre de façon détaillée le fonctionnement de ce processus.

Sécurité du réseau 

Les API doivent toujours utiliser le cryptage SSL. Ce protocole sécurise les données en transit, empêchant toute lecture non autorisée entre le serveur et le client. Vous pouvez identifier un point de terminaison sécurisé par l'utilisation du préfixe "https://" au lieu de "http://. Il renforce la confidentialité des données échangée entre le serveur et le client.

Dans le protocole HTTPS, le client ne fait confiance au serveur que s'il peut présenter un certificat valide signé par une autorité de certification de confiance préinstallée sur le client. Un attaquant pourrait tirer avantage de cela en installant un certificat malveillant d'autorité de certification racine sur l'appareil de l'utilisateur, incitant ainsi le client à faire confiance à tous les certificats signés par l'attaquant. Par conséquent, se reposer uniquement sur les certificats pourrait vous rendre vulnérable à une attaque de l'homme du milieu.

Le protocle SSL est une technique côté client visant à atténuer ce risque. Elle consiste à intégrer une liste de certificats de confiance dans le client pendant le développement. Ainsi, seules les requêtes signées avec l'un des certificats de confiance seront acceptées, tandis que les certificats auto-signés seront rejetés.

Conclusion

En conclusion, il n'existe pas de méthode infaillible pour assurer la sécurité, mais en adoptant des mesures conscientes, il est possible de réduire le risque de faille de sécurité de manière significative dans notre application. Il est primordial d'investir dans des mesures de sécurité proportionnelles à la sensibilité des données stockées dans l'application, au nombre d'utilisateurs et aux éventuels dommages qu'un pirate informatique pourrait causer en accédant à des comptes.

 

Références 

  1. «Securing React Native Applications», jscrambler,https://jscrambler.com/blog/securing-react-native-applications, (page consultée le 15 Mars 2024).
  2. «Security», React Native,  https://reactnative.dev/docs/security , (page consultée le 16 Mars 2024).
  3. «Bonnes pratiques concernant la sécurité des applications», Developers, https://developer.android.com/topic/security/best-practices?hl=fr#permissions, (page consultée le 16 Mars 2024).
  4. «Security», Runebook.dev, https://runebook.dev/fr/docs/react_native/security , (page consultee le 17 Mars 2024).
  5. « Les meilleures pratiques pour la sécurité des applications mobiles», Bemobee, https://bemobee.com/les-meilleures-pratiques-pour-la-securite-des-applications-mobiles/ , (page consultée le 18 Mars 2024).

Étiquettes

Commentaires