Le codage sécurisé s’attaque rapidement aux vulnérabilités telles que les XSS et les fuites de mémoire, ce qui renforce la résilience des logiciels et réduit les risques.
Les pratiques proactives permettent d’économiser du temps et de l’argent en évitant les correctifs coûteux après la publication et en renforçant la confiance des utilisateurs.
Les meilleures pratiques incluent la validation des entrées, la sécurisation du code tiers et l’utilisation d’outils tels que SAST pour des vérifications continues.
Les normes de l’OWASP, du CERT et du NIST aident les développeurs à créer des applications sécurisées et fiables.
Wiz Code prend en charge le codage sécurisé avec des analyses en temps réel, des commentaires exploitables et des conseils pour protéger votre SDLC.
Qu’est-ce que le codage sécurisé ?
Le codage sécurisé est la pratique consistant à développer des logiciels résistants aux vulnérabilités de sécurité en appliquant les meilleures pratiques, techniques et outils de sécurité dès le début du développement. Au lieu de penser uniquement à l’expérience utilisateur, le codage sécurisé aligne chaque fonctionnalité sur les mesures de sécurité, dès le début du cycle de vie du développement logiciel.
Par exemple, une application qui accepte toutes les données d’un client sans les nettoyer peut être plus facile à implémenter, à utiliser et à gérer. Cependant, il ouvre un point d’entrée pour les attaquants afin d’injecter du code malveillant.
The Secure Coding Best Practices [Cheat Sheet]
With curated insights and easy-to-follow code snippets, this 11-page cheat sheet simplifies complex security concepts, empowering every developer to build secure, reliable applications.
Download Cheat SheetWhy is secure coding important?
Le codage sécurisé intègre la sécurité dans l’ADN de votre logiciel pour éviter les vulnérabilités telles que l’injection SQL, les débordements de tampon, les scripts intersites, etc. Au-delà de la simple prévention des violations, il s’agit d’un moyen de préserver la confiance des utilisateurs, de déplacer la sécurité vers la gauche et de répondre aux normes strictes des lois sur la protection des données.
La récompense ? Moins de mauvaises surprises après le lancement, des applications plus puissantes et une meilleure protection pour les utilisateurs et votre organisation.
Sept techniques de codage sécurisé pour la création de logiciels sécurisés
Un processus de développement logiciel sécurisé commence par le respect des bonnes pratiques de codage qui permettent d’éviter les vulnérabilités et d’assurer la sécurité de vos applications. Si vous'Si vous recherchez une ressource plus approfondie, assurez-vous de consulter les exigences de codage sécurisé de l’OWASP dans leur Guide du développeur.
En attendant, voici quelques techniques clés que vous pouvez commencer à utiliser dès maintenant pour créer des systèmes logiciels plus sécurisés :
1. Utiliser des langages et des outils modernes
De nombreuses failles de sécurité liées à la mémoire affectent les langages de programmation avec une gestion manuelle de la mémoire et aucune vérification de la mémoire intégrée. Lorsque vous démarrez un nouveau projet, assurez-vous que vous avez vraiment besoin de C/C++ pour celui-ci, et si c’est le cas, utilisez Pointeurs intelligents et Analyseurs de code statiques pour minimiser l’impact des défauts de langue.
Si vous avez besoin de fonctionnalités de programmation système, un langage plus moderne comme Rouille peut être un bon choix car son système de type vérifie l’utilisation de la mémoire au moment de la compilation. Zig pourrait également être une bonne alternative, car il n’a pas de flux de contrôle caché ou d’allocations de mémoire.
Si vous n’avez pas besoin de fonctionnalités de programmation système, l’utilisation d’un langage de collecte des déchets comme Java ou C# peut vous protéger contre de nombreux problèmes de mémoire.
2. Valider et nettoyer les données d’entrée et de sortie
Les données utilisateur non validées sont la principale raison des failles d’injection. C’est pourquoi il est extrêmement important de valider toutes les données qui entrent dans votre système. L’assainissement est une autre étape qui permet de contrôler la sécurité sans sacrifier la facilité d’utilisation. Au lieu de rejeter une entrée utilisateur si elle n’est pas valide, l’assainissement supprimera les parties d’entrée problématiques (c’est-à-dire JavaScript dans HTML) et utilisera les données restantes. Lors de l’exécution dans un environnement client-serveur, assurez-vous que cette validation et cet assainissement se produisent sur le serveur. Cela signifie qu’il faut ajouter Validateurs et assainisseurs à tous les points de terminaison d’API qui acceptent les données utilisateur. Il peut également s’agir de choisir des formats de données faciles à valider, par exemple en acceptant un simple Markdown au lieu d’un HTML à part entière.
Il n’est pas toujours possible de garder les données d’entrée propres. Les bibliothèques de validation ont aussi des bogues. Pour vous assurer que rien ne s’infiltre dans vos utilisateurs, n’affichez que les sorties basées sur les entrées de l’utilisateur de manière sécurisée (c’est-à-dire ne rendez pas le HTML).
3. Vérifier l’intégrité du code tiers
Les bibliothèques et les frameworks tiers sont des bouées de sauvetage pour accélérer le développement, mais ils sont assortis de conditions : ils n’ont pas été construits dans votre maison. Traitez-les comme n’importe quelle intrant de votre processus de construction : soigneusement vérifiés et sous contrôle.
Vous voulez éviter les mauvaises surprises ? Épingler les dépendances à Versions ou hachages spécifiques pour empêcher les mises à jour non testées de se faufiler en production. L’audit et la mise à jour réguliers de ces bibliothèques n’ont rien de glamour, mais c’est le seul moyen d’éviter qu’un code obsolète ne devienne votre talon d’Achille.
4. Appliquez un contrôle d’accès strict
Le contrôle d’accès limite qui peut afficher ou modifier le code et les ressources, protégeant ainsi les fonctions et les données sensibles contre les utilisateurs non autorisés. Tenez-vous-en à la Principe du moindre privilège: ne donner aux utilisateurs que ce dont ils ont besoin pour faire leur travail, ni plus, ni moins.
Pour renforcer la sécurité, envisagez d’implémenter des contrôles d’accès basés sur les rôles (RBAC) et l’authentification multifacteur (MFA). Ces mesures réduisent davantage votre surface d’attaque et garantissent que les personnes non autorisées ne peuvent pas accéder aux systèmes ou aux données critiques.
5. Mettre en œuvre une gestion et une journalisation des erreurs appropriées
Personne ne veut donner une feuille de route aux attaquants, mais c’est exactement ce que peuvent faire des messages d’erreur trop détaillés. Gardez les détails internes (traces de pile et erreurs de base de données, par exemple) hors de la portée des utilisateurs. Enregistrez-les plutôt, de manière sécurisée et réfléchie, à l’attention de votre équipe uniquement.
De bons journaux racontent l’histoire : ce qui s’est passé, quand et pourquoi. Surveillez-les pour tout ce qui est louche, mais n’en faites pas trop en enregistrant des données sensibles. L’équilibre est la clé ici : vous dépannez, vous n’exposez pas.
6. Automatisez les révisions de code
Les révisions manuelles sont importantes, mais l’automatisation est nécessaire. Des outils automatisés tels que tests statiques de sécurité des applications (SAST) Et les linters signalent les vulnérabilités et les erreurs de codage plus rapidement que les humains ne le pourraient jamais.
Intégrez ces outils dans votre pipeline CI/CD, et chaque modification de code est réexaminée une fois avant d’être fusionnée. Un retour d’information immédiat permet aux développeurs de rester au courant et de s’assurer que les bonnes pratiques en matière de sécurité restent au premier plan.
7. Appliquer des techniques d’obfuscation de code
L’obfuscation du code ne rend pas votre application à l’épreuve des balles, mais elle ralentit les attaquants. Le renommage des variables en charabia, l’encodage de chaînes et la restructuration du code rendent plus difficile l’ingénierie inverse ou le vol de propriété intellectuelle.
Pensez-y comme à un camouflage supplémentaire : l’application fonctionne toujours sans problème pour les utilisateurs, mais les mauvais acteurs auront beaucoup plus de mal à s’introduire ou à donner un sens à ce qu’ils voient. Chaque obstacle compte.
Vulnérabilités logicielles courantes
Examinons les vulnérabilités de sécurité courantes identifiées par les développeurs de logiciels et les chercheurs en sécurité. Nous passerons de problèmes de bas niveau comme les vulnérabilités de mémoire à des problèmes de plus haut niveau comme les attaques par injection.
Débordements de mémoire tampon
Les débordements de mémoire tampon peuvent faire planter votre application ou permettre à des attaquants d’écrire des données dans d’autres mémoires tampons.
Les langages de programmation système comme C/C++ sont sujets à cette vulnérabilité. Ils autorisent et même exigent explicitement la gestion de la mémoire, mais ne vérifient pas l’accès à la mémoire avant qu’il ne soit trop tard. Si vous écrivez plus de données dans une mémoire tampon que vous ne l’avez attribuée au moment de la définition, C remplacera toutes les données de mémoire qui suivent à la fin de la mémoire tampon.
Exemple d’un buffer overflow en C :
int b[5] ;
b[5] = 999 ; buffer ne va que de 0 à 4
Utilisation après la livraison
L’utilisation après la libération se produit lorsque vous libérez de la mémoire sur le tas, mais que vous continuez à utiliser l’ancien pointeur.
Encore une fois, cette vulnérabilité est importante dans les langages sans nettoyage de la mémoire, comme C/C++, où vous devez gérer manuellement la mémoire. Il existe deux types de mémoire : la pile et le tas. Le langage gère automatiquement la pile, qui ne peut pas contenir de données dont les tailles dynamiques ne sont pas connues au moment de la compilation. Le tas est destiné aux données dynamiques, mais vous devez l’allouer manuellement et libérer de l’espace dessus. La libération signifie que vous dites au système d’exploitation que vous n’avez plus besoin de la mémoire, donc si vous l’utilisez par la suite avec un pointeur, l’accès illégal ira à un emplacement de mémoire non alloué.
Exemple d’utilisation après free en C :
char* p = (char*)malloc (16) ;
p = strdup("Du texte !");
gratuit(p) ;
printf("%s", p) ; Imprime ce qui se trouve maintenant dans la mémoire libérée
Double libre
Dans le cas de la double libération, vous libérez de la mémoire de tas après l’avoir déjà libérée.
La double libération est un problème dans les langages avec gestion manuelle de la mémoire, où vous devez indiquer explicitement au système d’exploitation que vous n’avez plus besoin d’une plage de mémoire spécifique. Si vous le faites deux fois, vous obtiendrez un plantage similaire à celui de l’utilisation après le problème gratuit. Cela se produit généralement lorsque vous avez plusieurs objets avec des pointeurs les uns vers les autres qui sont libérés à un moment donné. Double free peut corrompre la mémoire d’un pointeur référencé avant le premier free.
Exemple de double libre en C :
char* p = (char*)malloc (16) ;
p = strdup("Du texte !");
gratuit(p) ;
gratuit(p) ; corrompra ce qu’il y a dans la mémoire libérée
Désérialisation non sécurisée
La désérialisation non sécurisée consiste à transformer directement une structure de données externe (par exemple, JSON, XML, etc.) en une structure interne (par exemple, des objets, des tableaux, etc.) sans vérifications suffisantes.
La désérialisation non sécurisée est une vulnérabilité courante dans toutes sortes d’applications. Il peut être bon d’accepter des données non nettoyées pendant le développement, mais les utilisateurs peuvent introduire des données malveillantes sans préavis si cela est fait en production.
Exemple de désérialisation non sécurisée en JSON :
{
"nom": "exemple",
"Messagerie électronique": "email@example.com",
"isAdmin": true // doit être supprimé sur le serveur
}
Fuites de mémoire
Les fuites de mémoire permettent à votre application de consommer de la mémoire sans limites. Si vous épuisez la mémoire disponible et que vous en demandez d’autres, votre application se bloque.
Toute application suffisamment complexe est sensible à cette vulnérabilité. Même les langues collectées dans les ordures ne sont pas à l’abri des fuites de mémoire. Les langages de collecte de la mémoire vous permettent toujours de créer des structures de données qu’un ramasse-miettes ne peut pas gérer.
Défauts d’injection
L’exécution d’une entrée utilisateur en tant que code sans la valider est connue sous le nom de faille d’injection.
Ce problème peut affecter toutes les applications, quel que soit le langage de programmation utilisé. Une façon de rendre votre application vulnérable aux failles d’injection consiste à permettre aux utilisateurs d’ajouter du code personnalisé en tant que fonctionnalité et de ne pas mettre l’exécution en bac à sable correctement. Les débordements de mémoire tampon qui permettent aux attaquants d’écrire du code dans des emplacements de mémoire exécutable sont un autre moyen pour votre application de devenir vulnérable aux failles d’injection.
Cross-site scripting (XSS)
Le cross-site scripting est une version web spécifique d’une faille d’injection. Ici, un attaquant insère du code JavaScript personnalisé caché dans le balisage HTML.
XSS peut se produire sur tous les sites Web. Étant donné que le balisage et le code exécutable sont étroitement intégrés sur le Web, il est facile d’introduire JavaScript dans le HTML, ce qui laisse échapper des données sensibles.
Exemple de XSS en HTML et JavaScript :
<-- cela enverra une requête fetch
Lorsque la souris est sur le bouton <p> élément-->
<p onmouseover="fetch('//example.com')">Salut tout le monde!</p>
Entités externes XML (XXE)
Les entités externes XML sont un autre exemple de faille d’injection. Toutes les applications qui utilisent XML sont sensibles à cette attaque. L’idée derrière les entités externes en XML est de permettre la réutilisation de fichiers XML existants. Cependant, un attaquant peut utiliser cette fonctionnalité pour inclure des liens vers des fichiers XML privés, ce qui lui permet de lire indirectement des données privées via son fichier XML téléchargé.
Exemple d’injection d’entité XML externe :
<?xml version="1.0" encoding="Réf. ISO-8859-1"?>
<! DOCTYPE a [
<! ELEMENT a ANY >
<-- cela définit une nouvelle entité appelée xxe
à partir d’un fichier privé -->
<! SYSTÈME ENTITY xxe "file:///etc/passwd" >
]>
<-- ici, l’entité est rendue pour afficher
le contenu du fichier -->
<a>&xxe;</a>
Référence directe d’objet non sécurisée (IDOR)
Lorsque vous autorisez les API publiques à référencer directement des objets avec des ID séquentiels, les IDOR peuvent permettre aux attaquants de deviner l’ID de tous les objets sur le serveur.
Ce problème peut se produire partout où des ID séquentiels sont utilisés pour référencer des objets et est particulièrement grave lorsque vous utilisez les ID pour référencer des objets publics et privés sans nécessiter d’autorisation.
Exemples d’URL :
https://example.com/users/4539
https://example.com/users/4540
https://example.com/users/4541
Traversée de répertoire (alias traversée de chemin)
Une autre faille d’injection est que les attaquants peuvent traverser des chemins ou des structures de répertoires via des entrées de nom de fichier.
Toutes les applications qui autorisent la saisie de noms de fichiers peuvent être victimes de cette vulnérabilité. La traversée de répertoire peut se produire lorsque les utilisateurs téléchargent plusieurs fichiers se référant les uns aux autres via des chemins relatifs. Les attaquants peuvent utiliser des chemins de traversée de fichiers tels que ".." pour naviguer à partir de leur répertoire de téléchargement sur le serveur et dans les répertoires contenant des fichiers d’administrateurs ou d’autres utilisateurs.
Exemple de traversée de répertoire en JavaScript sur Node.js :
Cela charge un fichier javascript privé
const template = require(".. /.. /.. /serveur/config/base de données")
render(modèle)
Normes de sécurité du code
Les normes de codage sécurisé sont des ensembles de directives et de bonnes pratiques que les développeurs suivent pour créer des logiciels sécurisés et minimiser les vulnérabilités. Ils corrigent les erreurs de codage courantes et les faiblesses qui peuvent être exploitées par les attaquants, dans le but de créer un code plus résilient et résistant.
Vous trouverez ci-dessous les normes courantes de code sécurisé à suivre :
1. Pratiques de codage sécurisé de l’OWASP :
Les pratiques de codage sécurisé (SCP) de l’OWASP sont des lignes directrices de l’Open Web Application Security Project qui se concentrent sur les domaines clés pour améliorer la sécurité des logiciels, tels que la validation des entrées, l’authentification, la gestion des sessions, le cryptage et la gestion des erreurs. Il s’agit d’une feuille de route pour un code plus sûr, de votre S’engager d’abord pour le déploiement final.
2. Normes de codage sécurisé CERT :
Les normes de codage sécurisé (SCS) du CERT sont un ensemble de directives et de recommandations développées par le Software Engineering Institute (SEI) de l’Université Carnegie Mellon pour aider les développeurs à écrire du code sécurisé et à prévenir les vulnérabilités. Principaux domaines d’intervention :
Directives spécifiques à la langue :Proposer des recommandations pour C, C++, Java, Android et Perl afin de corriger les vulnérabilités courantes dans ces langages.
Programmation défensive :Mettre l’accent sur l’anticipation et la gestion des erreurs avec élégance pour éviter l’exploitation.
Gestion de la mémoire :Concentrez-vous sur la prévention des débordements de mémoire tampon et des fuites de mémoire, en particulier dans des langages comme C et C++.
3. Directives de codage sécurisé du NIST :
Les directives de codage sécurisé du NIST (également connues sous le nom de publication spéciale NIST 800-218) se concentrent sur des domaines critiques tels que la validation des entrées, l’authentification, le cryptage et la gestion des erreurs, offrant des conseils clairs pour empêcher les attaques par injection, le détournement de session et les problèmes de mémoire d’accéder à votre logiciel. Si vous voulez un sceau d’approbation garanti par le gouvernement sur votre Pratiques de sécurité du code, c’est votre choix.
ISO/IEC 27001 est une norme internationale de sécurité de l’information. Bien qu’il soit'Il ne s’agit pas spécifiquement d’une norme de codage sécurisé, mais elle comprend des exigences relatives aux pratiques de codage sécurisées dans le cadre d’une approche globale de gestion de la sécurité. L’annexe A, Contrôle 8.28 : Pratiques de codage sécuritaire, met l’accent sur le codage sécuritaire et met l’accent sur la façon dont les organisations doivent :
Développez des processus de codage sécurisés pour le développement interne et le code tiers.
Restez informé de l’évolution des menaces et des vulnérabilités.
Mettez en œuvre des principes de codage sécurisés robustes pour y répondre.
Assurez un cycle de vie de développement logiciel sécurisé avec Wiz
Le codage sécurisé est une pratique qui touche tous les aspects du développement de logiciels, du choix des formats de données et des langages de programmation à la planification des entrées et des sorties, en passant par la mise en œuvre.
Nous'Je suis ravi de vous présenter Wiz Code, notre dernière innovation conçue pour permettre aux développeurs et aux équipes de sécurité de mettre en œuvre et de maintenir des pratiques de codage sécurisées robustes tout au long du cycle de vie du développement logiciel !
Wiz Code étend sa plateforme de sécurité cloud pour couvrir toutes les étapes du développement, en offrant des capacités puissantes pour soutenir vos initiatives de codage sécurisé :
Lecture de code intégrée: Détectez les vulnérabilités, les erreurs de configuration et les problèmes de conformité directement dans votre IDE et vos référentiels de code, en détectant les problèmes potentiels avant qu’ils n’atteignent la production.
Retour d’information en temps réel sur la sécurité: Obtenez des informations de sécurité instantanées pendant que vous codez, ce qui permet aux développeurs de résoudre les problèmes immédiatement et d’apprendre les pratiques de codage sécurisé en déplacement.
Traçabilité du cloud au code: Retracez les risques découverts dans les environnements de production jusqu’au code spécifique et aux équipes qui les ont introduits, ce qui facilite l’analyse et la correction rapides des causes profondes.
Conseils de correction dans le code: Recevez des recommandations exploitables et contextuelles pour résoudre les problèmes de sécurité directement dans votre environnement de développement.
Prise en charge linguistique complète: Bénéficiez des meilleures pratiques de codage sécurisé sur un large éventail de langages et de frameworks de programmation.
Secure your SDLC from start to finish
See why Wiz is one of the few cloud security platforms that security and devops teams both love to use.