Sécurité des applications C# : top 10 des vulnérabilités que tout développeur doit connaître
Le développement en C# et sur la plateforme .NET est un outil puissant pour créer des applications d'entreprise et web. Cependant, même le code le plus fiable peut contenir des failles qui entraîneront une fuite de données, une perte de réputation et des pertes financières. Dans cet article, nous analyserons les 10 vulnérabilités les plus courantes des applications C#, basées sur l'OWASP Top 10, avec des exemples pratiques et des méthodes de protection.
1. Injections SQL (SQL Injection)
C'est l'une des menaces les plus anciennes, mais toujours d'actualité. La vulnérabilité survient lorsque la saisie utilisateur est directement concaténée dans une requête SQL.
Code vulnérable :
string userName = Request.QueryString["name"];string query = "SELECT * FROM Users WHERE Name = '" + userName + "'";SqlCommand cmd = new SqlCommand(query, connection);Code sécurisé (requêtes paramétrées) :
string userName = Request.QueryString["name"];string query = "SELECT * FROM Users WHERE Name = @name";SqlCommand cmd = new SqlCommand(query, connection);cmd.Parameters.AddWithValue("@name", userName);Recommandation : Utilisez toujours des requêtes paramétrées ou Entity Framework, qui échappe automatiquement la saisie.
2. Scripting inter-sites (XSS)
Les attaques XSS permettent à un attaquant d'injecter un script malveillant dans une page web. En C#, cela se produit souvent lors de l'affichage de données non vérifiées via @Html.Raw().
Code vulnérable :
@Html.Raw(Model.Comment)Code sécurisé (encodage de la sortie) :
@Html.Encode(Model.Comment)Recommandation : Utilisez la syntaxe Razor @Model.Comment (elle encode automatiquement le HTML) et n'appliquez jamais @Html.Raw() sans vérification.
3. Contrefaçon de requête inter-sites (CSRF)
La CSRF force un utilisateur authentifié à effectuer une action non désirée sur le site (par exemple, un transfert d'argent). Dans ASP.NET Core, la protection est intégrée, mais elle doit être correctement activée.
Code vulnérable (absence de jeton antifalsification) :
<form method="post" action="/Account/Delete"> <button type="submit">Supprimer le compte</button></form>Code sécurisé (avec AntiForgeryToken) :
<form method="post" action="/Account/Delete"> @Html.AntiForgeryToken() <button type="submit">Supprimer le compte</button></form>Recommandation : Ajoutez l'attribut [ValidateAntiForgeryToken] à vos méthodes POST et utilisez @Html.AntiForgeryToken() dans les formulaires.
4. Stockage non sécurisé des mots de passe
Stocker les mots de passe en texte clair ou en utilisant des hachages faibles (MD5, SHA1) est une erreur grave.
Code vulnérable :
string passwordHash = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(password));Code sécurisé (utilisation de bcrypt/Argon2) :
using BCrypt.Net;string passwordHash = BCrypt.HashPassword(password, workFactor: 12);Recommandation : Utilisez les bibliothèques BCrypt.Net ou Microsoft.AspNetCore.Identity, qui génèrent automatiquement un sel et utilisent des algorithmes modernes.
5. Divulgation de données confidentielles dans les exceptions
Afficher la pile d'erreurs complète à l'utilisateur peut révéler la structure de l'application, les chaînes de connexion et les chemins de fichiers.
Code vulnérable (en production) :
catch (Exception ex){ return Content(ex.ToString());}Code sécurisé :
catch (Exception ex){ _logger.LogError(ex, "Erreur lors du traitement de la requête"); return StatusCode(500, "Erreur interne du serveur");}Recommandation : Ne divulguez jamais les détails des exceptions aux clients. Utilisez un système de journalisation (logging) et renvoyez des messages d'erreur génériques.