Check-list de revue de code de sécurité

Imaginez que la valeur de votre marché chute de 80 % en neuf heures. C’est exactement ce qui est arrivé à Holograph. Une violation de données récente a révélé une faiblesse cachée dans le code du contrat intelligent d’Holograph, un rappel brutal que la cybercriminalité est en plein essor. C’est là qu’un audit de sécurité du code devient non négociable.

Les entreprises qui manipulent des données sensibles ont la responsabilité de donner la priorité à des mesures de sécurité robustes. Que vous soyez un géant du e-commerce, une agence gouvernementale ou un fournisseur de services financiers, ce guide vous fournira les connaissances et les outils nécessaires pour améliorer la sécurité de votre code. De nombreuses réglementations exigent une protection solide des données, et les audits vous aident à vous conformer à ces règles.

Cet article fournit une liste de contrôle complète pour effectuer un audit de sécurité de code approfondi. En suivant ces étapes, vous pouvez améliorer considérablement la sécurité de votre code et conserver la confiance inébranlable de vos clients et investisseurs.

Guide d'audit complet de la sécurité du code

Un audit de sécurité du code est une analyse approfondie du code de votre application, à la recherche de vulnérabilités cachées. Dans les secteurs à haut risque, même une faille de sécurité mineure peut avoir des conséquences désastreuses. Un audit de sécurité du code permet d’identifier et de résoudre ces problèmes avant qu’ils ne deviennent un problème majeur.

Check-list de revue de code de sécurité

Vérifications préliminaires

Avant de plonger dans les détails de l’audit de sécurité de votre code, il est crucial de comprendre les menaces et vulnérabilités potentielles qui rôdent dans votre application. Ces premières étapes permettent de préparer le terrain pour un processus d’examen approfondi et efficace.

Comprendre le contexte de l’application :

  • Recueillir des informations sur le but, l’architecture et la pile technologique de l’application.
  • Identifier les composants et modules clés qui nécessitent un examen de sécurité.
  • Comprendre le modèle de menaces, y compris les attaquants potentiels et leurs capacités.
  • Examiner toute documentation de sécurité existante et les évaluations de sécurité précédentes.
  • Identifier les exigences réglementaires et de conformité pertinentes pour l’application.

Gestion du contrôle de version et des modifications :

  • S’assurer que le code est stocké dans un système de contrôle de version sécurisé tel que Git.
  • Examiner l’historique des commits pour comprendre les modifications récentes et identifier les problèmes de sécurité potentiels.
  • Vérifier que les modifications de code sont examinées et approuvées via un processus formel.
  • Vérifier la présence de messages de commit et de documentation liés à la sécurité.
  • Identifier les commits directs sur des zones sensibles du code sans examen par les pairs.

Processus de construction et de déploiement :

  • Examiner les processus de construction et de déploiement pour les meilleures pratiques de sécurité.
  • S’assurer que les scripts de construction et les fichiers de configuration sont sécurisés et n’exposent pas d’informations sensibles.
  • Vérifier l’utilisation d’outils de test de sécurité automatisés dans le pipeline CI/CD.
  • Vérifier la gestion sécurisée des secrets et des identifiants pendant les processus de construction et de déploiement.
  • Identifier les étapes manuelles dans le processus de déploiement qui pourraient introduire des risques de sécurité.

Collaboration et communication d’équipe :

  • Établir des canaux de communication clairs et des protocoles pour le processus d’examen de sécurité.
  • S’assurer que tous les membres de l’équipe impliqués dans l’examen sont conscients de leurs rôles et responsabilités.
  • Planifier des réunions régulières pour discuter des conclusions et coordonner les efforts de remédiation.
  • Fournir une formation et des ressources aux membres de l’équipe sur les pratiques de codage sécurisé et les techniques d’examen de sécurité.

Qualité du code et vérification des vulnérabilités

Dans cette étape, nous nous concentrons sur l’assurance de la meilleure qualité de code possible et sur l’élimination de tous les points faibles susceptibles d’être piratés. Nous allons examiner le code pour trouver des problèmes de sécurité courants et nous assurer que tout est codé selon les meilleures pratiques.

Lisibilité et maintenabilité du code :

  • Vérifiez que le code est clair, concis et auto-explicatif, avec des commentaires appropriés
  • Assurez-vous que les fonctions et les méthodes ont un objectif unique et ne sont pas trop complexes
  • Vérifiez l’utilisation cohérente des conventions de nommage et du formatage du code dans l’ensemble de la base de code
  • Identifiez et refactorez le code dupliqué pour réduire le risque d’erreurs
  • Assurez une structure de code modulaire pour des tests et une maintenance plus faciles
// Bad practice
public void ProcessOrder(Order order) {
    ValidateOrder(order);
    SaveOrder(order);
    SendConfirmationEmail(order);
}

// Good practice
public void ProcessOrder(Order order) {
    ValidateOrder(order);
    SaveOrder(order);
    NotifyCustomer(order);
}

private void NotifyCustomer(Order order) {
    SendConfirmationEmail(order);
    LogNotification(order);
}
Un code monolithique qui n’est pas divisé en petites parties peut entraîner une duplication du code et augmente le risque d’erreurs lors des modifications. Refactorez les grands blocs de code en méthodes ou classes plus petites et réutilisables

Analyse statique :

  • Utilisez des outils d’analyse statique pour scanner le code à la recherche de vulnérabilités de sécurité potentielles
  • Identifiez les problèmes de codage courants tels que les débordements de tampon, les conditions de concurrence et les fuites de mémoire
  • Assurez-vous que les outils d’analyse statique sont configurés pour appliquer les normes de codage et les directives de sécurité
  • Examinez et traitez les résultats des rapports d’analyse statique
  • Intégrez l’analyse statique dans le pipeline d’intégration continue (CI) pour des vérifications continues

Normes de codage et meilleures pratiques :

  • Vérifiez le respect des pratiques de codage spécifiques au langage et aux normes de l’industrie
  • Vérifiez l’utilisation de bibliothèques et de frameworks de codage sécurisés
  • Assurez-vous que le code respecte le principe du moindre privilège
  • Validez que les fonctions obsolètes ou non sécurisées ne sont pas utilisées
  • Promouvez l’utilisation de techniques de codage défensif pour anticiper et gérer les entrées ou états inattendus
// Bad practice
public void ProcessInput(string input) {
    Console.WriteLine("Processing: " + input.Substring(5));
}

// Good practice
public void ProcessInput(string input) {
    if (string.IsNullOrEmpty(input) || input.Length < 5)
    {
        throw new ArgumentException("Input must be at least 5 characters long.");
    }
    Console.WriteLine("Processing: " + input.Substring(5));
}
Exemple de codage défensif qui rend le code plus sécurisé, mais aussi plus facile à déboguer et à maintenir

Utilisation sécurisée des fonctionnalités du langage :

  • Vérifiez l’utilisation correcte des fonctionnalités spécifiques au langage, telles que la gestion des exceptions en Java ou la vérification des erreurs en Go
  • Assurez-vous que la gestion de la mémoire est effectuée correctement pour éviter les fuites et la corruption (pertinent pour les langages comme C/C++)
  • Vérifiez l’utilisation sûre des constructions de programmation concurrente pour éviter les conditions de concurrence et les interblocages
  • Assurez-vous que la sécurité des types est appliquée pour prévenir les vulnérabilités liées aux types
  • Validez que les opérations d’entrée/sortie sont gérées de manière sécurisée pour prévenir les attaques par injection
// Bad practice
char* buffer = new char[100];
strcpy(buffer, "This is a buffer.");
// Missing delete[] buffer;

// Good practice
#include 
std::unique_ptr buffer(new char[100]);
strcpy(buffer.get(), "This is a buffer.");
// No need to manually delete, handled by unique_ptr
Exemple de gestion de mémoire mauvaise vs bonne en C/C++. Les problèmes de mémoire peuvent entraîner des plantages d’applications, une dégradation des performances et des vulnérabilités de sécurité

Reconnaissance des modèles de vulnérabilité :

  • Identifiez et traitez les modèles de vulnérabilité courants, tels que les identifiants codés en dur ou les secrets dans le code source
  • Inspectez l’utilisation non sécurisée des générateurs de nombres aléatoires (assurez-vous que des générateurs cryptographiques sont utilisés si nécessaire)
  • Assurez-vous qu’il n’y a pas d’entrées utilisateur non assainies qui sont directement transmises aux requêtes de base de données ou aux arguments de ligne de commande
  • Documentez toute instance de canaux de communication non sécurisés sans chiffrement
  • Surveillez les contrôles d’accès insuffisants dans la logique de l’application
  • Documentez et partagez ces modèles avec l’équipe de développement pour sensibiliser et prévenir les occurrences futures
// Bad practice (SQL Injection risk)
string query = "SELECT * FROM Users WHERE Username = '" + username + "'";

// Good practice
string query = "SELECT * FROM Users WHERE Username = @username";
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("@username", username);
L’utilisation directe d’entrées non assainies peut entraîner des injections SQL, des injections de commandes et d’autres types d’attaques par injection

Analyse de la complexité du code :

  • Utilisez des outils pour mesurer les métriques de complexité du code, telles que la complexité cyclomatique
  • Identifiez les zones de code très complexes ou « points chauds » qui sont sujettes aux erreurs et aux problèmes de sécurité
  • Simplifiez les chemins de code complexes pour améliorer la lisibilité et réduire la probabilité de bugs
  • Assurez-vous que la logique de sécurité critique est simple et facile à examiner
  • Refactorez le code si nécessaire pour réduire la complexité et améliorer la clarté
// Bad practice
public void ProcessOrder(Order order) {
    ValidateOrder(order);
    if (order.IsValid) {
        SaveOrder(order);
        SendConfirmationEmail(order);
    }
}

// Good practice
public void ProcessOrder(Order order) {
    if (!ValidateOrder(order)) return;
    SaveOrder(order);
    SendConfirmationEmail(order);
}

private bool ValidateOrder(Order order) {
    // Validation logic
    return order.IsValid;
}
Refactorez les méthodes volumineuses en méthodes plus petites, chacune effectuant une responsabilité unique, ce qui améliore la testabilité, la lisibilité et la maintenabilité

Documentation et commentaires :

  • Assurez-vous que le code pertinent pour la sécurité est bien documenté, en expliquant la justification des contrôles de sécurité
  • Vérifiez que les commentaires n’exposent pas d’informations sensibles ou de détails d’implémentation de sécurité
  • Assurez-vous que la documentation comprend des directives pour une interaction sûre avec le code, par exemple, comment appeler correctement une fonction qui effectue des opérations sensibles
  • Validez que toutes les implémentations cryptographiques et les processus de gestion des clés sont minutieusement documentés
  • Assurez-vous que les commentaires en ligne sont utilisés judicieusement pour clarifier les segments de code complexes sans encombrer la base de code

Validation des entrées

Une validation adéquate des entrées est essentielle pour garantir que seules des données valides et attendues sont traitées par l’application. Cela permet de prévenir une variété d’attaques, telles que l’injection SQL, le cross-site scripting (XSS) et les débordements de tampon. Toutes les entrées doivent être correctement validées et assainies avant d’être traitées, et voici comment vérifier cela.

Validation côté client :

  • Vérifiez que la validation côté client est implémentée pour fournir un retour immédiat aux utilisateurs
  • Assurez-vous que la validation côté client n’est pas la seule mesure de sécurité utilisée
  • Vérifiez la présence de règles de validation cohérentes entre le côté client et le côté serveur

Validation côté serveur :

  • Assurez-vous que toutes les entrées sont validées côté serveur, indépendamment de la validation côté client
  • Vérifiez si les entrées sont validées à l’aide de listes d’autorisation
  • Vérifiez si des listes de refus pourraient être mises en œuvre comme mesure secondaire
  • Assurez une validation correcte de tous les types d’entrées, y compris les chaînes, les nombres, les dates et les fichiers
// Bad practice
public bool ValidateUsername(string username) {
    // Checks only if input is not null or empty
    return !string.IsNullOrEmpty(username);
}

//Good practice
public bool ValidateUsername(string username) {
    // Allow only alphanumeric characters and underscores
    Regex allowedPattern = new Regex(@"^w+$");
    return allowedPattern.IsMatch(username);
}
Utilisation de modèles de validation génériques et trop permissifs par rapport à l’utilisation de listes d’autorisation pour spécifier explicitement les caractères ou modèles autorisés

Assainissement des entrées :

  • Vérifier que les entrées HTML, JavaScript et SQL sont correctement assainies pour prévenir les attaques par injection
  • S’assurer que des bibliothèques ou fonctions spécialisées sont utilisées pour gérer les tâches courantes d’assainissement
  • S’assurer que les entrées assainies sont utilisées de manière cohérente dans toute l’application

Vérifications de longueur et de format :

  • Vérifier que les longueurs des entrées sont vérifiées pour éviter les débordements de tampon et l’épuisement des ressources
  • S’assurer que les entrées sont conformes aux formats attendus, tels que les adresses e-mail, les numéros de téléphone et les URL
  • Vérifier si des expressions régulières sont implémentées pour une validation de format complexe, en s’assurant qu’elles sont efficaces et sécurisées
// Bad practice
public IActionResult SubmitForm(string userInput) {
    // No length check
    Database.Save(userInput); // Risk of buffer overflow or inefficient database use
}

//Good practice
public IActionResult SubmitForm(string userInput) {
    if (userInput.Length > 100) {
        return BadRequest("Input too long.");
    }
    Database.Save(userInput); // Input length is controlled
}
Toujours vérifier la longueur des entrées avant de les traiter pour s’assurer qu’elles répondent aux exigences de votre application et éviter une mauvaise utilisation des ressources

Analyse des valeurs limites :

  • Tester la validation des entrées par rapport aux valeurs limites, telles que les valeurs maximales et minimales autorisées
  • S’assurer que les valeurs hors limites sont correctement gérées et ne provoquent pas de plantages de l’application
  • Valider les entrées numériques pour s’assurer qu’elles se situent dans les plages acceptables et qu’elles sont correctement typées (par exemple, entiers par rapport aux nombres à virgule flottante)
// Bad practice
public IActionResult CreateAccount(User user) {
    if (user.Age < 18) { // No upper boundary check
        return BadRequest("You must be at least 18 years old.");
    }
    UserRepository.Add(user);
}

//Good practice
public IActionResult CreateAccount(User user) {
    if (user.Age < 18 || user.Age > 99) {
        return BadRequest("Invalid age. Age must be between 18 and 99.");
    }
    UserRepository.Add(user);
}
Ignorer les valeurs limites lors de la validation peut entraîner des comportements ou des erreurs inattendus lorsque des valeurs extrêmes sont saisies

Vérification des types :

  • S’assurer que les entrées sont vérifiées pour leurs types de données corrects, tels que chaînes de caractères, entiers, booléens
  • Vérifier si des fonctions et bibliothèques de type sécurisé sont utilisées pour appliquer les contraintes de type de données
  • Valider les entrées JSON et XML pour s’assurer qu’elles sont conformes aux schémas et structures attendus
// Bad practice
public void ProcessJson(string jsonString) {
    var data = JsonConvert.DeserializeObject(jsonString); // No validation against schema
    // Process data
}

// Good practice
public IActionResult ProcessJson(string jsonString) {
    JSchema schema = JSchema.Parse(File.ReadAllText("MyObjectSchema.json"));
    JObject jsonObject = JObject.Parse(jsonString);
    if (!jsonObject.IsValid(schema)) {
        return BadRequest("Invalid JSON format.");
    }
    var data = jsonObject.ToObject();
    // Process data
}
Accepter des données JSON ou XML sans les valider par rapport à un schéma, ce qui pourrait entraîner la transmission de structures de données incorrectes

Encodage :

  • S’assurer que les données d’entrée sont correctement encodées avant d’être traitées ou stockées
  • Vérifier si des techniques d’encodage appropriées sont utilisées pour différents contextes, tels que l’encodage URL, l’encodage HTML et l’encodage base64
  • Vérifier que les données encodées sont correctement décodées et validées avant tout traitement ultérieur
// Bad practice
public string GetUserProfileHtml(string username) {
    return $"
Hello, {username}!
"; // Risk of XSS if username contains HTML/JS } // Good practice public string GetUserProfileHtml(string username) { return $"
Hello, {HttpUtility.HtmlEncode(username)}!
"; // Safely encode to prevent XSS }
Afficher les entrées utilisateur non encodées dans du HTML, ce qui peut entraîner des vulnérabilités de type Cross-Site Scripting (XSS)

Téléchargements de fichiers :

  • Valider le type, la taille et le contenu du fichier avant d’accepter les téléchargements
  • S’assurer que les fichiers téléchargés sont stockés dans un emplacement sécurisé avec un accès restreint
  • Vérifier si une analyse antivirus et une détection de logiciels malveillants sont implémentées pour les fichiers téléchargés
  • Vérifier que les noms et chemins de fichiers sont assainis pour prévenir les attaques par traversée de répertoire

Entrées tierces :

  • Valider et assainir les entrées reçues de sources tierces, telles que les API et les webhooks
  • S’assurer que les données tierces sont traitées avec le même niveau de scrutiny que les entrées utilisateur
  • Vérifier l’intégrité et l’authenticité des données reçues de sources externes

Authentification

L’authentification est cruciale pour vérifier l’identité de l’utilisateur et s’assurer que seuls les utilisateurs légitimes peuvent accéder au système. Une authentification appropriée protège vos informations et tout ce qui se trouve dans le système contre les regards indiscrets. Une récente violation de données chez Snowflake a confirmé que les utilisateurs disposant d’une authentification à facteur unique peuvent servir de porte d’entrée aux pirates pour compromettre des centaines d’autres comptes.

Gestion des mots de passe :

  • S’assurer que les mots de passe sont stockés à l’aide d’algorithmes de hachage robustes tels que bcrypt, Argon2 ou Scrypt
  • Vérifier la mise en œuvre des politiques de mots de passe, y compris la longueur minimale, la complexité et les exigences d’expiration
  • Vérifier l’existence de mécanismes sécurisés de réinitialisation et de récupération de mot de passe qui n’exposent pas d’informations sensibles
  • S’assurer que les utilisateurs sont invités à changer les mots de passe par défaut lors de la première connexion
// Bad practice
public bool IsValidPassword(string password) {
    return !string.IsNullOrEmpty(password); // Only checks if password is not empty
}

// Good practice
public bool IsValidPassword(string password) {
    var hasMinimum8Chars = password.Length >= 10;
    var hasUpperCase = password.Any(char.IsUpper);
    var hasLowerCase = password.Any(char.IsLower);
    var hasDecimalDigit = password.Any(char.IsDigit);
    var hasSpecialChar = password.Any(p => !char.IsLetterOrDigit(p));

    return hasMinimum8Chars && hasUpperCase && hasLowerCase && hasDecimalDigit && hasSpecialChar;
}
Mettre en œuvre et faire respecter des politiques de mots de passe qui exigent une longueur minimale et incluent des exigences de complexité

Authentification multifacteur (MFA) :

  • S’assurer que la MFA est implémentée et appliquée pour les comptes et opérations utilisateur critiques
  • Vérifier l’utilisation de seconds facteurs sécurisés, tels que les jetons matériels, les codes SMS ou les applications d’authentification
  • S’assurer que les mécanismes de MFA sont résilients aux attaques courantes telles que le phishing et les attaques de l’homme du milieu
  • Valider l’implémentation de la MFA pour divers flux d’authentification, tels que la connexion et la réinitialisation du mot de passe

Mécanismes de connexion sécurisés :

  • Valider la mise en œuvre de formulaires de connexion sécurisés, en s’assurant que les données sont transmises via HTTPS
  • S’assurer que les tentatives de connexion sont limitées en fréquence pour prévenir les attaques par force brute
  • Vérifier la gestion sécurisée des jetons de session et des cookies pendant le processus d’authentification
  • S’assurer que les messages d’erreur de connexion ne révèlent pas si le nom d’utilisateur ou le mot de passe était incorrect
// Bad practice
public IActionResult Login(string username, string password) {
    if (Authenticate(username, password)) {
        // User authenticated
    } else {
        // Authentication failed
    }
}

// Good practice
public IActionResult Login(string username, string password) {
    if (!IsAllowedToAttempt(username)) {
        return BadRequest("Too many failed login attempts. Please try again later.");
    }

    if (Authenticate(username, password)) {
        ResetAttemptCounter(username);
        // User authenticated
    } else {
        IncrementAttemptCounter(username);
        // Authentication failed
    }
}
Autoriser des tentatives de connexion illimitées sans aucune vérification par rapport à la mise en œuvre d’une limitation de débit pour prévenir les attaques par force brute

Authentification par jeton :

  • S’assurer de la génération, du stockage et de la validation sécurisés des jetons d’authentification, tels que JWT et OAuth
  • Vérifier que les jetons sont signés et chiffrés à l’aide d’algorithmes robustes
  • Inspecter si des jetons à courte durée de vie et des jetons de rafraîchissement sont implémentés pour minimiser l’impact du vol de jetons
  • S’assurer que les jetons sont invalidés lors de la déconnexion de l’utilisateur ou de l’expiration de la session

Autorisation

Une fois l’utilisateur authentifié, l’autorisation vérifie ce qu’il est autorisé à faire. Cette partie de l’application garantit que seuls les utilisateurs ayant les bonnes permissions peuvent accéder à des éléments spécifiques ou effectuer certaines actions. Lorsque nous procédons à un audit, voici ce que nous recherchons.

Contrôle d’accès basé sur les rôles (RBAC) :

  • S’assurer que les rôles et permissions des utilisateurs sont clairement définis et mis en œuvre
  • Vérifier que les contrôles d’accès sont effectués côté serveur pour chaque opération sensible
  • S’assurer que les utilisateurs ne peuvent effectuer que des actions et accéder aux ressources correspondant à leurs rôles
// Bad practice
public bool CanAccessResource(string role)
{
    if (role == "Admin" || role == "User") // Unclear distinction
        return true;
    return false;
}

// Good practice
public bool CanAccessResource(string role)
{
    if (role == "Admin")
        return true;
    if (role == "User")
        return false; // Specific access defined per role
}
Définitions de rôles ambiguës par rapport à des rôles et permissions clairement définis

Principe du moindre privilège :

  • Vérifiez que l’application applique le principe du moindre privilège, en accordant aux utilisateurs les permissions minimales nécessaires
  • Assurez-vous que les actions sensibles nécessitent une autorisation ou une confirmation supplémentaire
  • Vérifiez si la séparation des tâches est mise en œuvre pour prévenir les conflits d’intérêts
  • Demandez s’il existe un examen et un audit réguliers des rôles et permissions des utilisateurs pour identifier les privilèges excessifs

Listes de contrôle d’accès (ACL) :

  • Assurez-vous que les ACL sont mises en œuvre pour contrôler l’accès aux ressources en fonction des rôles et attributs des utilisateurs
  • Vérifiez le stockage et la manipulation sécurisés des ACL
  • Vérifiez l’application cohérente des ACL dans toute l’application
  • Inspectez si les ACL sont régulièrement mises à jour pour refléter les changements dans les rôles et permissions des utilisateurs

Contrôle d’accès basé sur les attributs (ABAC) :

  • Vérifiez la mise en œuvre de l’ABAC, en vous assurant que les décisions d’accès sont basées sur les attributs de l’utilisateur et les conditions environnementales
  • Assurez-vous que les politiques d’ABAC sont clairement définies et régulièrement révisées
  • Validez que les règles ABAC sont appliquées de manière cohérente dans toute l’application
  • Assurez-vous que les politiques sont flexibles pour s’adapter aux changements de rôles d’utilisateurs et de conditions environnementales

Génération et stockage de jetons de session :

  • Vérifiez l’utilisation de générateurs de nombres aléatoires cryptographiquement sécurisés pour la création de jetons
  • Vérifiez que les jetons de session ont une longueur et une complexité suffisantes pour prévenir les attaques par devinettes
  • Assurez-vous que les jetons de session sont stockés en toute sécurité côté client, en utilisant des cookies sécurisés avec les attributs appropriés, tels que HttpOnly, Secure, SameSite
  • Vérifiez que les jetons de session ne sont pas exposés dans les URL ou d’autres emplacements non sécurisés
// Bad practice
public string GenerateSimpleToken() {
    return Guid.NewGuid().ToString().Substring(0, 8);  // Too short and not complex enough
}

// Good practice
public string GenerateSecureToken() {
    using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) {
        byte[] tokenData = new byte[64]; // 512 bits
        rng.GetBytes(tokenData);
        return Convert.ToBase64String(tokenData);  // Long and complex
    }
}
Assurez-vous que les jetons de session ont une longueur et une complexité suffisantes pour prévenir les attaques par devinettes

Expiration et invalidation de session :

  • Implémentez des politiques d’expiration de session pour limiter la durée des sessions, réduisant ainsi le risque de détournement
  • Vérifiez que les sessions sont invalidées lors de la déconnexion de l’utilisateur ou en cas d’inactivité
  • Assurez-vous que les jetons de session sont invalidés lors des changements de mot de passe ou d’autres événements de sécurité critiques
  • Implémentez des mécanismes pour détecter et terminer les sessions dupliquées ou simultanées du même utilisateur
  • Implémentez des délais d’expiration de session inactifs pour déconnecter automatiquement les utilisateurs après une période d’inactivité
  • Vérifiez que les délais d’expiration de session sont correctement configurés pour équilibrer sécurité et commodité pour l’utilisateur
// Bad practice
public void ChangePassword(string newPassword) {
    // Password is changed, but session remains valid
    UpdatePassword(newPassword);
}

// Good practice
public void Logout() {
    Session.Abandon();  // Invalidate the session upon logout
}

public void ChangePassword(string newPassword) {
    UpdatePassword(newPassword);
    Session.Abandon();  // Invalidate the session after a password change
}
Invalidez les jetons de session lors d’événements sensibles à la sécurité pour prévenir le détournement de session

Audit et journalisation :

  • Assurez-vous que les événements d’authentification et d’autorisation sont enregistrés à des fins de surveillance et d’audit
  • Vérifiez que les journaux incluent des détails tels que l’ID de l’utilisateur, l’action effectuée et l’horodatage
  • Assurez-vous que les journaux ne contiennent pas d’informations sensibles et qu’ils sont stockés en toute sécurité

Sécurité des fonctions d’administration :

  • Assurez-vous que les fonctions et interfaces administratives sont protégées par des mécanismes d’authentification et d’autorisation robustes
  • Vérifiez que les actions administratives sont journalisées et surveillées pour toute activité suspecte
  • Vérifiez si des mesures de sécurité supplémentaires, telles que l’authentification multifacteur (MFA) et la liste blanche d’adresses IP, sont mises en œuvre pour les comptes d’administrateur
  • Assurez-vous que les fonctions administratives sont segmentées et uniquement accessibles aux utilisateurs autorisés

Protection des données

La protection des données garantit que les informations sensibles sont traitées de manière sécurisée tout au long de leur cycle de vie, de la collecte et du stockage au traitement et à la mise au rebut. Voici comment vous pouvez protéger les données de vos utilisateurs pour prévenir les accès non autorisés, les violations et les fuites de données. Des pratiques de protection des données solides sont essentielles pour maintenir la conformité en matière de confidentialité des données lors du traitement d’informations personnelles ou réglementées.

Chiffrement des données :

  • Assurez-vous que les données sensibles sont chiffrées au repos et en transit à l’aide d’algorithmes de chiffrement robustes (AES-256, TLS 1.2/1.3) et de protocoles de communication (HTTPS, SSH)
  • Vérifiez que les clés de chiffrement sont gérées de manière sécurisée, avec des pratiques appropriées de rotation et de stockage des clés
  • Assurez-vous que seul le personnel autorisé a accès aux clés de chiffrement et autres identifiants de sécurité
  • Assurez-vous que les champs de base de données contenant des informations sensibles sont chiffrés
// Bad practice
string encryptionKey = "1234567890123456";  // Hard-coded encryption key

//Good practice
// Using Azure Key Vault for managing encryption keys
var keyVault = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(securityTokenService));
var secret = await keyVault.GetSecretAsync("https://myvault.vault.azure.net/secrets/mysecret/");
Utilisez un système sécurisé de gestion des clés, tel qu’Azure Key Vault ou AWS Key Management Service, pour gérer les clés de chiffrement

Masquage et anonymisation des données :

  • Assurez-vous que les données sensibles sont masquées ou anonymisées lorsqu’elles sont affichées dans les interfaces utilisateur ou les journaux
  • Mettez en œuvre des techniques de masquage des données pour les environnements de non-production afin d’éviter l’exposition de données réelles
  • Vérifiez l’efficacité des techniques d’anonymisation pour empêcher la ré-identification des individus
  • Assurez-vous que les données sensibles ne sont pas exposées dans les messages d’erreur ou les journaux de débogage

Stockage sécurisé des données :

  • Vérifiez que les données sensibles sont stockées dans des environnements sécurisés et contrôlés par accès
  • Assurez-vous que les bases de données et les systèmes de fichiers sont configurés avec des paramètres de sécurité appropriés
  • Examinez si des plans de sauvegarde et de reprise après sinistre qui incluent le stockage sécurisé des données de sauvegarde sont mis en œuvre
  • Testez les processus de sauvegarde et de récupération pour garantir que les données peuvent être restaurées en toute sécurité

Intégrité des données :

  • Mettez en œuvre des contrôles pour garantir l’intégrité des données pendant le stockage et la transmission
  • Vérifiez l’utilisation de hachages cryptographiques pour détecter la falsification des données
  • Assurez-vous que les processus de validation des données incluent des contrôles d’intégrité
  • Surveillez et enregistrez les problèmes d’intégrité des données pour l’audit et le dépannage

Conservation et suppression des données :

  • Assurez la conformité avec les politiques de conservation des données, en ne stockant les données que le temps nécessaire
  • Vérifiez si des techniques de suppression sécurisée des données sont en place pour supprimer définitivement les données sensibles lorsqu’elles ne sont plus nécessaires
  • Vérifiez que les processus d’élimination des données sont complets et documentés

Conformité réglementaire :

  • Assurez-vous que l’application est conforme aux réglementations pertinentes en matière de protection des données, telles que le RGPD, le CCPA et la HIPAA
  • Vérifiez la mise en œuvre des mécanismes de consentement de l’utilisateur pour la collecte et le traitement des données
  • Assurez-vous que les utilisateurs peuvent exercer leurs droits en matière de protection des données, tels que l’accès, la correction et la suppression
  • Vérifiez si les pratiques et politiques de protection des données sont documentées pour démontrer la conformité lors des audits

Surveillance et journalisation :

  • Vérifiez si des systèmes de surveillance sont mis en œuvre pour détecter les accès non autorisés aux données sensibles
  • Examinez les journaux à la recherche de signes de violations de données ou d’autres incidents de sécurité

Réponse aux violations de données :

  • Assurez-vous qu’un plan de réponse aux violations de données est en place et testé régulièrement
  • Vérifiez que le plan comprend des procédures pour identifier, contenir et atténuer les violations de données

Gestion des données par des tiers :

  • Assurez-vous que les prestataires de services tiers respectent les exigences en matière de protection des données
  • Vérifiez que les données partagées avec des tiers sont chiffrées et transmises de manière sécurisée
  • Vérifiez si des accords de partage de données décrivant les responsabilités et les mesures de sécurité sont mis en œuvre

Gestion des erreurs

Une gestion appropriée des erreurs garantit que l’application gère les erreurs avec grâce, maintient sa fonctionnalité et n’expose pas d’informations sensibles. Votre application dispose-t-elle de mécanismes de gestion des erreurs robustes ? Il est grand temps de le découvrir !

Gestion gracieuse des erreurs :

  • Assurez-vous que l’application gère les erreurs avec grâce sans exposer d’informations sensibles
  • Vérifiez que des messages d’erreur conviviaux sont affichés, en évitant les détails techniques qui pourraient aider les attaquants
  • Vérifiez que les mécanismes de gestion des erreurs empêchent les plantages de l’application et maintiennent la fonctionnalité dans la mesure du possible

Erreurs de validation des entrées :

  • Validez que toutes les erreurs de validation des entrées sont gérées de manière appropriée, en fournissant un retour clair aux utilisateurs
  • Assurez-vous que les erreurs de validation ne révèlent pas d’informations sensibles ni de détails sur la logique de l’application
  • Vérifiez la gestion cohérente des erreurs de validation dans toute l’application
// Bad practice
if (!UserExists(username)) {
    return Error("Username not found.");
}
if (!CorrectPassword(username, password)) {
    return Error("Incorrect password.");
}

// Good practice
if (!Authenticate(username, password)) {
    return Error("Invalid username or password.");
}
Utilisez des messages d’erreur génériques qui ne révèlent pas quelle partie de l’authentification a échoué

Gestion des exceptions :

  • Vérifiez que toutes les exceptions sont interceptées et gérées correctement, empêchant ainsi les plantages de l’application
  • Assurez-vous que les blocs try-catch sont utilisés de manière appropriée pour gérer les exceptions sans en exposer les détails à l’utilisateur
  • Vérifiez si des gestionnaires d’exceptions globaux sont mis en œuvre pour gérer les erreurs inattendues et les enregistrer en toute sécurité

Gestion des ressources :

  • Assurez-vous que les ressources telles que les connexions de base de données, les fichiers et les sockets réseau sont correctement fermées et libérées après une erreur
  • Vérifiez que les fuites de ressources sont évitées en mettant en œuvre une gestion robuste des erreurs pour la gestion des ressources

Scénarios spécifiques de gestion des erreurs :

  • Validez que l’application gère correctement les scénarios d’erreur spécifiques, tels que les pannes réseau, les erreurs de base de données et les pannes de services tiers
  • Assurez-vous que des mécanismes de repli sont en place pour maintenir la fonctionnalité de l’application pendant ces erreurs

Journalisation

Des pratiques de journalisation sécurisées sont cruciales pour surveiller le fonctionnement de l’application, diagnostiquer les problèmes et soutenir les enquêtes de sécurité. N’oubliez pas que les journaux doivent être détaillés, sécurisés et conformes aux réglementations.

Sensibilité des journaux :

  • Assurez-vous que les informations sensibles, telles que les mots de passe, les clés API et les données personnelles, ne sont jamais enregistrées
  • Vérifiez que les journaux sont nettoyés pour supprimer ou masquer toute information sensible avant le stockage
  • Vérifiez si des politiques de journalisation définissant quelles informations peuvent et ne peuvent pas être enregistrées sont en place

Complétude et détail des journaux :

  • Assurez-vous que les journaux capturent suffisamment de détails pour diagnostiquer les problèmes et retracer les activités
  • Vérifiez que les journaux incluent des informations critiques telles que les horodatages, les ID d’utilisateur, les adresses IP et les détails des erreurs
  • Assurez-vous que les entrées de journal sont cohérentes et structurées pour une analyse facile
// Bad practice
Log.Error("Operation failed"); // Bad: No context or details provided

// Good practice
Log.Error($"Operation failed at {DateTime.UtcNow} by UserID {userID}. Error: {errorDetail}");
Des journaux (logs) sans les détails nécessaires rendent le dépannage difficile

Sécurité du stockage des journaux :

  • Vérifiez que les journaux sont stockés dans un endroit sécurisé avec un accès restreint
  • Assurez-vous que les journaux sont protégés contre toute falsification en mettant en œuvre des vérifications d’intégrité ou des protections cryptographiques
  • Inspectez si des politiques de rétention sont appliquées pour archiver ou supprimer en toute sécurité les journaux après une période spécifiée
// Bad practice
var logFilePath = @"C:SharedFolderapplog.txt";

// Good practice
var logFilePath = @"C:SecureLogsapplog.txt";
FileSystemAccessRule rule = new FileSystemAccessRule("LogAccessGroup", FileSystemRights.ReadData, AccessControlType.Allow);
Stockage des journaux dans un dossier partagé par rapport au stockage dans un emplacement sécurisé avec accès restreint basé sur les rôles

Surveillance et alertes des journaux :

  • Assurez-vous que les mécanismes de journalisation incluent une surveillance en temps réel pour détecter et répondre aux événements de sécurité
  • Vérifiez que des alertes sont configurées pour les erreurs critiques, les incidents de sécurité et les activités suspectes
  • Vérifiez si des outils de surveillance sont mis en œuvre pour analyser les données des journaux et générer des informations exploitables

Rotation et maintenance des journaux :

  • Vérifiez si des politiques de rotation des journaux sont appliquées pour gérer la taille des fichiers journaux et maintenir les performances
  • Assurez-vous que les anciens journaux sont archivés en toute sécurité et peuvent être récupérés pour analyse si nécessaire
  • Vérifiez que les processus de rotation et d’archivage des journaux ne perturbent pas la fonctionnalité de journalisation

Bibliothèques et dépendances tierces

Pour accélérer le développement de fonctionnalités, les développeurs utilisent souvent des bibliothèques tierces. Mais tout comme une brique défectueuse affaiblit un mur, une bibliothèque vulnérable ou une intégration non sécurisée peut exposer votre application. Un exemple frappant est Cylance, dont les données ont été volées via une plateforme tierce. C’est pourquoi les composants externes doivent être correctement maintenus pour minimiser de telles conséquences.

Gestion des dépendances :

  • Assurez-vous que toutes les bibliothèques tierces et dépendances sont gérées à l’aide d’un gestionnaire de paquets, tel que npm, pip ou Maven
  • Vérifiez qu’une politique claire est en place pour l’ajout de nouvelles dépendances, incluant les évaluations de sécurité et les approbations
  • Recherchez la présence d’un fichier manifeste de dépendances (par exemple, package.json, requirements.txt) qui liste toutes les dépendances et leurs versions

Contrôle de version et mises à jour :

  • Vérifiez si les bibliothèques tierces sont mises à jour vers les dernières versions sécurisées
  • Assurez-vous que les mises à jour de dépendances sont testées dans un environnement de staging avant d’être déployées en production
  • Surveillez les avis de sécurité et les bases de données de vulnérabilités (par exemple, CVE, NVD) pour les mises à jour des dépendances utilisées
  • Utilisez des outils automatisés d’analyse de vulnérabilités, tels que Snyk, Dependabot, OWASP Dependency-Check, pour détecter les vulnérabilités connues dans les bibliothèques tierces
  • Examinez la réputation et l’activité de maintenance des auteurs et contributeurs de la bibliothèque

Conformité des licences :

  • Assurez-vous que toutes les bibliothèques tierces sont conformes aux politiques de licence de l’organisation
  • Vérifiez que les licences de toutes les dépendances sont documentées et examinées pour la conformité légale
  • Soyez attentif aux bibliothèques ayant des licences restrictives ou incompatibles qui pourraient entraîner des problèmes juridiques

Isolation et sandboxing :

  • Vérifiez si les bibliothèques tierces sont isolées dans un environnement contrôlé pour limiter leur impact sur l’application
  • Assurez-vous que des techniques de sandboxing sont mises en œuvre pour exécuter le code tiers avec des permissions restreintes
  • Garantissez que les composants tiers n’ont pas d’accès inutile aux données sensibles ou aux ressources système

Revue de code et audit :

  • Examinez le code source des bibliothèques tierces critiques pour identifier les problèmes de sécurité potentiels
  • Assurez-vous que les bibliothèques tierces font l’objet d’audits de sécurité réguliers par leurs mainteneurs ou des auditeurs tiers
  • Vérifiez que les bibliothèques disposent d’un processus transparent pour signaler et résoudre les vulnérabilités de sécurité

Configuration et personnalisation :

  • Assurez-vous que les bibliothèques tierces sont configurées de manière sécurisée, conformément aux meilleures pratiques
  • Si applicable, inspectez toutes les personnalisations et examinez-les pour leurs implications en matière de sécurité

Surveillance et alertes :

  • Vérifiez si des outils de surveillance sont mis en place pour suivre les performances et le comportement des bibliothèques tierces en production
  • Vérifiez si des alertes sont configurées pour les activités anormales ou les problèmes de performance liés aux composants tiers
  • Examinez les journaux et les métriques pour identifier les incidents de sécurité potentiels impliquant des bibliothèques tierces

Audit de sécurité du code : ce que vous pouvez attendre de ce service

Votre produit nécessite un audit de sécurité du code approfondi. Vous comparez les fournisseurs, mais vous vous demandez peut-être : qu’obtiendrai-je exactement ? Comment utiliserai-je les résultats ? Nous pouvons vous aider ! Chez Redwerk, nous décomposons les conclusions de votre audit de code en étapes claires et réalisables.

1. Rapport facile à comprendre

Nous vous fournissons une liste de problèmes avec des explications et pourquoi ils sont importants. Le rapport est bien structuré et divisé en Revue d’architecture, Revue de base de données, Qualité du code, Couverture des tests et Revue de sécurité.

Ce rapport devient votre feuille de route pour résoudre les problèmes et améliorer votre produit. Par exemple, nous avons aidé Complete Network à identifier un problème de sécurité critique lié au stockage de données sensibles dans un dossier accessible au public. Nous avons également partagé trois moyens simples d’améliorer les performances de l’application, ainsi que d’autres améliorations de la qualité du code, ce qui a entraîné une maintenabilité 80% plus élevée.

2. Recommandations d'experts

Nous ne nous contentons pas de signaler les problèmes ; nous proposons des solutions. Notre rapport comprend des recommandations sur la façon de résoudre chaque problème et d’améliorer la qualité globale de votre code. De plus, nous classons les vulnérabilités par gravité, afin que vous sachiez par quoi commencer.

Par exemple, lors de la revue d’une application de cartographie réseau, nous avons identifié que la qualité du code était le principal coupable. L’architecture était solide et il n’y avait aucun problème de sécurité. Cependant, le code backend était écrit de manière à rendre le développement futur et l’intégration de nouveaux développeurs coûteux.

3. Corrigez vous-même ou laissez-nous vous aider

Vous avez le contrôle ! Utilisez notre rapport avec n’importe quel développeur – votre équipe interne, des freelances, ou qui que vous fassiez confiance. Mais si vous souhaitez un coup de main, nous pouvons résoudre les problèmes nous-mêmes. Notre rapport comprend même une estimation du temps nécessaire pour résoudre tous les bugs.

Arrêtez les problèmes de code avant qu’ils ne commencent. Contactez-nous dès maintenant pour obtenir une image claire de la santé de votre application !

Découvrez comment nous avons audité le logiciel de gestion de devis Project Science de Complete Network, obtenant une augmentation de 80% de la maintenabilité du code

Veuillez saisir votre adresse courriel professionnelle n'est pas un courriel professionnel