Treize règles pour développer des applications Java sécurisées

La sécurité est l'un des aspects les plus complexes, les plus vastes et les plus importants du développement logiciel. La sécurité des logiciels est également souvent négligée ou simplifiée à l'excès par quelques ajustements mineurs à la fin du cycle de développement. Nous pouvons voir les résultats dans la liste annuelle des principales violations de la sécurité des données, qui représentaient en 2019 plus de 3 milliards d'enregistrements exposés. Si cela peut arriver à Capital One, cela peut vous arriver.

La bonne nouvelle est que Java est une plate-forme de développement de longue date avec de nombreuses fonctionnalités de sécurité intégrées. Le package Java Security a subi des tests de combat intensifs et est fréquemment mis à jour pour détecter de nouvelles vulnérabilités de sécurité. La nouvelle API de sécurité Java EE, publiée en septembre 2017, corrige les vulnérabilités des architectures cloud et microservices. L'écosystème Java comprend également un large éventail d'outils pour le profilage et le signalement des problèmes de sécurité. 

Mais même avec une plateforme de développement solide, il est important de rester vigilant. Le développement d'applications est une entreprise complexe et les vulnérabilités peuvent se cacher dans le bruit de fond. Vous devriez penser à la sécurité à chaque étape du développement d'une application, des fonctionnalités de langage au niveau de la classe à l'autorisation de point de terminaison d'API.

Les règles de base suivantes offrent une bonne base pour créer des applications Java plus sécurisées.

Règle de sécurité Java n ° 1: Écrivez du code Java propre et fort

Les vulnérabilités aiment se cacher dans la complexité, alors gardez votre code aussi simple que possible sans sacrifier les fonctionnalités. L'utilisation de principes de conception éprouvés comme DRY (ne vous répétez pas) vous aidera à écrire du code plus facile à examiner pour les problèmes.  

Exposez toujours le moins d'informations possible dans votre code. Le masquage des détails d'implémentation prend en charge le code qui est à la fois maintenable et sécurisé. Ces trois conseils contribueront grandement à l'écriture de code Java sécurisé:

  • Faites bon usage des modificateurs d'accès de Java . Savoir comment déclarer différents niveaux d'accès pour les classes, les méthodes et leurs attributs contribuera grandement à protéger votre code. Tout ce qui peut être rendu privé doit être privé. 
  • Évitez la réflexion et l'introspection . Il y a des cas où de telles techniques avancées sont justifiées, mais pour la plupart, vous devriez les éviter. L'utilisation de la réflexion élimine le typage fort, ce qui peut introduire des points faibles et une instabilité dans votre code. La comparaison des noms de classe en tant que chaînes est sujette aux erreurs et peut facilement conduire à une collision d'espace de noms.
  • Définissez toujours les plus petites surfaces d'API et d'interface possibles . Découpez les composants et faites-les interagir sur la plus petite zone possible. Même si une zone de votre application est infectée par une faille, d'autres seront en sécurité. 

Règle de sécurité Java n ° 2: éviter la sérialisation

C'est une autre astuce de codage, mais elle est suffisamment importante pour être une règle en soi. La sérialisation prend une entrée distante et la transforme en un objet entièrement doté. Il supprime les constructeurs et les modificateurs d'accès et permet à un flux de données inconnues de devenir du code en cours d'exécution dans la JVM. Par conséquent, la sérialisation Java est profondément et intrinsèquement non sécurisée.

La fin de la sérialisation Java

Si vous ne l'avez pas entendu, Oracle a des plans à long terme pour supprimer la sérialisation de Java. Mark Reinhold, architecte en chef du groupe de plates-formes Java chez Oracle, a déclaré qu'il pensait qu'un tiers ou plus de toutes les vulnérabilités Java impliquaient une sérialisation.

Autant que possible, évitez la sérialisation / désérialisation dans votre code Java. Au lieu de cela, envisagez d'utiliser un format de sérialisation tel que JSON ou YAML. N'exposez jamais, jamais un point de terminaison de réseau non protégé qui reçoit et agit sur un flux de sérialisation. Ce n'est rien d'autre qu'un tapis de bienvenue pour le chaos.

Règle de sécurité Java n ° 3: ne jamais exposer les informations d'identification ou les informations personnelles non chiffrées

C'est difficile à croire, mais cette erreur évitable cause de la douleur année après année.

Lorsqu'un utilisateur entre un mot de passe dans le navigateur, il est envoyé en texte clair à votre serveur. Ce devrait être la dernière fois qu’elle verra le jour. Vous devez chiffrer le mot de passe via un chiffrement unidirectionnel avant de le conserver dans la base de données, puis recommencer chaque fois que vous comparez à cette valeur.

Les règles relatives aux mots de passe s'appliquent à toutes les informations personnelles identifiables (PII): cartes de crédit, numéros de sécurité sociale, etc. Toute information personnelle confiée à votre application doit être traitée avec le plus grand soin.

Les informations d'identification ou PII non chiffrées dans une base de données sont une faille de sécurité béante, attendant qu'un attaquant soit découvert. De même, n'écrivez jamais d'informations d'identification brutes dans un journal ou ne les transmettez pas à un fichier ou au réseau. Au lieu de cela, créez un hachage salé pour vos mots de passe. Assurez-vous de faire vos recherches et d'utiliser un algorithme de hachage recommandé.

Passer à la règle n ° 4: utilisez toujours une bibliothèque pour le chiffrement; ne roulez pas le vôtre.

Règle de sécurité Java n ° 4: utiliser des bibliothèques connues et testées

Régalez-vous des yeux sur cette question-réponse sur le déploiement de votre propre algorithme de sécurité. La leçon tl; dr est la suivante: utilisez autant que possible des bibliothèques et des frameworks connus et fiables. Cela s'applique à tout le spectre, du hachage de mot de passe à l'autorisation de l'API REST.

Heureusement, Java et son écosystème sont là pour vous. Pour la sécurité des applications, Spring Security est la norme de facto. Il offre un large éventail d'options et la flexibilité pour s'adapter à toute architecture d'application, et il intègre une gamme d'approches de sécurité.

Votre premier instinct pour aborder la sécurité devrait être de faire vos recherches. Recherchez les meilleures pratiques, puis recherchez quelle bibliothèque mettra en œuvre ces pratiques pour vous. Par exemple, si vous envisagez d'utiliser des jetons Web JSON pour gérer l'authentification et l'autorisation, examinez la bibliothèque Java qui encapsule JWT, puis apprenez à l'intégrer dans Spring Security.

Même en utilisant un outil fiable, il est assez facile de brouiller l'autorisation et l'authentification. Assurez-vous de bouger lentement et vérifiez tout ce que vous faites.

Règle de sécurité Java n ° 5: soyez paranoïaque à propos des entrées externes

Qu'il s'agisse d'un utilisateur tapant dans un formulaire, une banque de données ou une API distante, ne faites jamais confiance aux entrées externes.

L'injection SQL et les scripts intersites (XSS) ne sont que les attaques les plus connues pouvant résulter d'une mauvaise gestion des entrées externes. Un exemple moins connu - l'un parmi tant d'autres - est «l'attaque d'un milliard de rires», par laquelle l'expansion d'entités XML peut provoquer une attaque par déni de service.

Chaque fois que vous recevez une entrée, elle doit être vérifiée et désinfectée. Cela est particulièrement vrai de tout ce qui pourrait être présenté à un autre outil ou système pour traitement. Par exemple, si quelque chose pouvait devenir un argument pour une ligne de commande de système d'exploitation: méfiez-vous!

Une instance spéciale et bien connue est l'injection SQL, qui est traitée dans la règle suivante.

Règle de sécurité Java n ° 6: utilisez toujours des instructions préparées pour gérer les paramètres SQL

Chaque fois que vous créez une instruction SQL, vous risquez d'interpoler un fragment de code exécutable.

Sachant cela, il est recommandé de toujours utiliser la classe java.sql.PreparedStatement pour créer du SQL. Des installations similaires existent pour les magasins NoSQL comme MongoDB. Si vous utilisez une couche ORM, l'implémentation utilisera PreparedStatements pour vous sous le capot.

Règle de sécurité Java n ° 7: ne pas révéler l'implémentation via des messages d'erreur

Les messages d'erreur en production peuvent être une source d'informations fertile pour les attaquants. Les traces de pile, en particulier, peuvent révéler des informations sur la technologie que vous utilisez et la manière dont vous l'utilisez. Évitez de révéler les traces de pile aux utilisateurs finaux.

Les alertes d'échec de connexion entrent également dans cette catégorie. Il est généralement admis qu'un message d'erreur doit être donné comme «Échec de la connexion» par opposition à «N'a pas trouvé cet utilisateur» ou «Mot de passe incorrect». Offrez le moins d'aide possible aux utilisateurs potentiellement malveillants.

Idéalement, les messages d'erreur ne doivent pas révéler la pile technologique sous-jacente de votre application. Gardez ces informations aussi opaques que possible.

Règle de sécurité Java n ° 8: maintenir les versions de sécurité à jour

À partir de 2019, Oracle a mis en œuvre un nouveau schéma de licence et un nouveau calendrier de publication pour Java. Malheureusement pour les développeurs, la nouvelle cadence de publication ne facilite pas les choses. Néanmoins, vous êtes responsable de vérifier fréquemment les mises à jour de sécurité et de les appliquer à votre JRE et JDK.

Assurez-vous de connaître les correctifs critiques disponibles en consultant régulièrement la page d'accueil d'Oracle pour les alertes de sécurité. Chaque trimestre, Oracle fournit une mise à jour automatisée des correctifs pour la version actuelle LTS (support à long terme) de Java. Le problème est que ce correctif n'est disponible que si vous payez pour une licence de support Java.

Si votre organisation paie pour une telle licence, suivez la procédure de mise à jour automatique. Sinon, vous utilisez probablement OpenJDK, et vous devrez faire les correctifs vous-même. Dans ce cas, vous pouvez appliquer le correctif binaire ou simplement remplacer votre installation OpenJDK existante par la dernière version. Alternativement, vous pouvez utiliser un OpenJDK commercialement pris en charge comme Zulu Enterprise d'Azul.

Avez-vous besoin de tous les correctifs de sécurité?

Si vous surveillez attentivement les alertes de sécurité, vous constaterez peut-être que vous n'avez pas besoin d'un ensemble donné de mises à jour. Par exemple, la version de janvier 2020 semble être une mise à jour Java critique; cependant, une lecture attentive montre que la mise à jour corrige uniquement les failles de sécurité des applets Java et n'affecte pas les serveurs Java.

Règle de sécurité Java n ° 9: recherchez les vulnérabilités de dépendance

Il existe de nombreux outils disponibles pour analyser automatiquement votre base de code et vos dépendances à la recherche de vulnérabilités. Tout ce que vous avez à faire est de les utiliser.

OWASP, l'Open Web Application Security Project, est une organisation dédiée à l'amélioration de la sécurité du code. La liste OWASP d'outils d'analyse de code automatisés fiables et de haute qualité comprend plusieurs outils orientés Java.

Vérifiez régulièrement votre base de code, mais gardez également un œil sur les dépendances tierces. Les attaquants ciblent à la fois les bibliothèques open source et les bibliothèques fermées. Surveillez les mises à jour de vos dépendances et mettez à jour votre système à mesure que de nouveaux correctifs de sécurité sont publiés.

Règle de sécurité Java n ° 10: Surveiller et enregistrer l'activité des utilisateurs

Même une simple attaque par force brute peut réussir si vous ne surveillez pas activement votre application. Utilisez des outils de surveillance et de journalisation pour garder un œil sur la santé des applications.

Si vous souhaitez être convaincu de l'importance de la surveillance, asseyez-vous et regardez les paquets TCP sur le port d'écoute de vos applications. Vous verrez toutes sortes d'activités, bien au-delà des simples interactions des utilisateurs. Certaines de ces activités seront des robots et des méchants qui recherchent des vulnérabilités.

Vous devez enregistrer et surveiller les tentatives de connexion infructueuses et déployer des contre-mesures pour empêcher les clients distants d'attaquer en toute impunité.

La surveillance peut vous alerter de pics inexpliqués et la journalisation peut aider à démêler ce qui n'a pas fonctionné après une attaque. L'écosystème Java comprend une multitude de solutions commerciales et open source pour la journalisation et la surveillance.

Règle de sécurité Java n ° 11: faites attention aux attaques par déni de service (DoS)

Chaque fois que vous traitez des ressources potentiellement coûteuses ou que vous entreprenez des opérations potentiellement coûteuses, vous devez vous prémunir contre une utilisation excessive des ressources.

Oracle maintient une liste de vecteurs potentiels pour ce type de problème dans son document Secure Coding Guidelines for Java SE, sous la rubrique «Denial Of Service».

Fondamentalement, chaque fois que vous effectuez une opération coûteuse, comme la décompression d'un fichier compressé, vous devez surveiller l'explosion de l'utilisation des ressources. Ne faites pas confiance aux fichiers manifestes. Faites confiance uniquement à la consommation réelle sur disque ou en mémoire, surveillez-la et évitez les excès de mise à genoux du serveur.

De même, dans certains traitements, il est important de surveiller les boucles éternelles inattendues. Si une boucle est suspecte, ajoutez un garde qui garantit que la boucle progresse et court-circuitez-la si elle semble être devenue zombie.

Règle de sécurité Java n ° 12: envisagez d'utiliser le gestionnaire de sécurité Java

Java dispose d'un gestionnaire de sécurité qui peut être utilisé pour restreindre les ressources auxquelles un processus en cours d'exécution a accès. Il peut isoler le programme en ce qui concerne l'accès au disque, à la mémoire, au réseau et à la JVM. La réduction de ces exigences pour votre application réduit l'empreinte des dommages potentiels d'une attaque. Un tel isolement peut également être gênant, c'est pourquoi il SecurityManagern'est pas activé par défaut.

Vous devrez décider vous-même si le fait de contourner SecurityManagerles opinions fortes de vos applications vaut la peine de fournir une protection supplémentaire. Consultez la documentation Oracle pour en savoir plus sur la syntaxe et les fonctionnalités du gestionnaire de sécurité Java.

Règle de sécurité Java n ° 13: envisagez d'utiliser un service d'authentification cloud externe

Certaines applications doivent simplement posséder leurs données utilisateur; pour le reste, un fournisseur de services cloud pourrait avoir du sens.

Recherchez autour de vous et vous trouverez une gamme de fournisseurs d'authentification cloud. L'avantage d'un tel service est que le fournisseur est responsable de la sécurisation des données sensibles des utilisateurs, pas vous. D'autre part, l'ajout d'un service d'authentification augmente la complexité de l'architecture de votre entreprise. Certaines solutions, comme l'authentification FireBase, incluent des SDK pour l'intégration à travers la pile.

Conclusion

J'ai présenté 13 règles pour développer des applications Java plus sécurisées. Ces règles sont éprouvées, mais la plus grande règle de toutes est la suivante: méfiez-vous. Abordez toujours le développement logiciel avec méfiance et une perspective de sécurité. Recherchez les vulnérabilités dans votre code, tirez parti des API et des packages de sécurité Java, et utilisez des outils tiers pour surveiller et enregistrer votre code pour les problèmes de sécurité.

Voici trois bonnes ressources de haut niveau pour rester au courant du paysage de la sécurité Java en constante évolution:

  • Top 10 de l'OWASP
  • Top 25 CWE
  • Directives relatives au code sécurisé d'Oracle

Cette histoire, "Treize règles pour le développement d'applications Java sécurisées" a été initialement publiée par JavaWorld.