1. Qu'est-ce qu'une attaque par injection SQL ?
L'attaque dite par injection SQL signifie que l'attaquant insère des commandes SQL dans le champ de saisie d'un formulaire Web ou dans la chaîne de requête d'une requête de page, et trompe le serveur en lui faisant exécuter des commandes SQL malveillantes. Dans certains formulaires, les entrées utilisateur sont utilisées directement pour construire (ou affecter) des commandes SQL dynamiques, ou comme paramètres d'entrée pour des procédures stockées. De tels formulaires sont particulièrement vulnérables aux attaques par injection SQL. Les processus d'attaque par injection SQL courants incluent :
⑴ Une application Web ASP.NET possède une page de connexion. Cette page de connexion contrôle si l'utilisateur a le droit d'accéder à l'application. Elle nécessite que l'utilisateur saisisse un nom et un mot de passe.
⑵ Le contenu saisi dans la page de connexion sera directement utilisé pour construire des commandes SQL dynamiques, ou directement utilisé comme paramètres de procédures stockées. Voici un exemple d'application ASP.NET construisant une requête :
System.Text.StringBuilder query = new System.Text.StringBuilder(
"SELECT * parmi les utilisateurs WHERE login = '")
.Append(txtLogin.Text).Append("' AND password='")
.Append(txtPassword.Text).Append("'");
⑶ L'attaquant saisit quelque chose comme "' ou '1'='1" dans les zones de saisie du nom d'utilisateur et du mot de passe.
⑷ Une fois le contenu saisi par l'utilisateur soumis au serveur, le serveur exécute le code ASP.NET ci-dessus pour construire une commande SQL pour interroger l'utilisateur. Cependant, comme le contenu saisi par l'attaquant est très spécial, la commande SQL finale. devient : SELECT * from Users WHERE login = '' ou '1'='1' AND password = '' ou '1'='1'.
⑸ Le serveur exécute une requête ou un processus stocké pour comparer les informations d'identité saisies par l'utilisateur avec les informations d'identité enregistrées sur le serveur.
⑹ Étant donné que la commande SQL a effectivement été modifiée par l'attaque par injection et ne peut pas véritablement authentifier l'identité de l'utilisateur, le système autorisera l'attaquant de manière incorrecte.
Si un attaquant sait que l'application utilisera le contenu saisi dans le formulaire directement pour des requêtes de vérification d'identité, il tentera de saisir des chaînes SQL spéciales pour falsifier la requête afin de modifier sa fonctionnalité d'origine et tromper le système pour qu'il accorde des autorisations d'accès.
Selon l'environnement système, les dommages qu'un attaquant peut causer sont également différents, et sont principalement déterminés par les autorisations de sécurité de l'application pour accéder à la base de données. Si le compte de l'utilisateur dispose de droits d'administrateur ou d'autres droits relativement avancés, l'attaquant peut effectuer diverses opérations sur les tables de la base de données qu'il souhaite effectuer, notamment l'ajout, la suppression ou la mise à jour de données, voire la suppression directe de la table.
2. Comment prévenir ?
Heureusement, il n'est pas particulièrement difficile d'empêcher les applications ASP.NET d'être piratées par des attaques par injection SQL. Il vous suffit de filtrer tout le contenu d'entrée avant d'utiliser le contenu d'entrée du formulaire pour construire la commande SQL. Le filtrage des entrées peut être effectué de différentes manières.
⑴ Pour les situations où les requêtes SQL sont construites dynamiquement, les techniques suivantes peuvent être utilisées :
Premièrement : remplacer les guillemets simples, c'est-à-dire remplacer tous les guillemets simples par deux guillemets simples pour empêcher les attaquants de modifier la signification des commandes SQL. En regardant à nouveau l'exemple précédent, "SELECT * from Users WHERE login = ''' or ''1''=''1' AND password = ''' or ''1''=''1'" obtiendra évidemment le même "SELECT * from Users WHERE login = '' ou '1'='1' AND password = '' ou '1'='1'" des résultats différents.
Deuxièmement : supprimez tous les traits d'union dans le contenu des entrées utilisateur pour empêcher les attaquants de construire des requêtes telles que "SELECT * from Users WHERE login = 'mas' -- AND password =''", car le suffixe de ces requêtes a été commenté pour la moitié. et n'est plus valide. L'attaquant a seulement besoin de connaître un nom de connexion d'utilisateur légal et n'a pas besoin de connaître le mot de passe de l'utilisateur pour réussir à accéder.
Troisièmement : limitez les autorisations du compte de base de données utilisé pour exécuter les requêtes. Utilisez différents comptes d'utilisateurs pour effectuer des opérations de requête, d'insertion, de mise à jour et de suppression. En isolant les opérations pouvant être effectuées par différents comptes, il évite que l'endroit initialement utilisé pour exécuter la commande SELECT soit utilisé pour exécuter la commande INSERT, UPDATE ou DELETE.
⑵ Utilisez des procédures stockées pour exécuter toutes les requêtes. La manière dont les paramètres SQL sont transmis empêchera les attaquants d'utiliser des guillemets simples et des traits d'union pour mener des attaques. En outre, il permet également de restreindre les autorisations de la base de données pour autoriser uniquement l'exécution de procédures stockées spécifiques. Toutes les entrées utilisateur doivent être conformes au contexte de sécurité de la procédure stockée appelée, de sorte que les attaques par injection soient difficiles à produire.
⑶ Limitez la longueur du formulaire ou de la chaîne de requête saisie. Si le nom de connexion de l'utilisateur ne comporte qu'un maximum de 10 caractères, n'acceptez pas plus de 10 caractères saisis dans le formulaire. Cela augmentera considérablement la difficulté pour les attaquants d'insérer du code nuisible dans les commandes SQL.
⑷ Vérifiez la légalité de la saisie de l'utilisateur et assurez-vous que le contenu saisi ne contient que des données légales. L'inspection des données doit être effectuée à la fois côté client et côté serveur - la validation côté serveur est effectuée pour compenser la sécurité fragile du mécanisme de validation côté client.
Côté client, il est tout à fait possible pour un attaquant d'obtenir le code source de la page web, de modifier le script qui vérifie la légalité (ou de supprimer directement le script), puis de soumettre le contenu illégal au serveur via le formulaire modifié. Par conséquent, la seule façon de garantir que l’opération de vérification a réellement été effectuée est d’effectuer également une vérification côté serveur. Vous pouvez utiliser de nombreux objets de validation intégrés, tels que RegularExpressionValidator, qui peuvent générer automatiquement des scripts côté client pour la validation, et bien sûr, vous pouvez également insérer des appels de méthode côté serveur. Si vous ne trouvez pas d'objet de validation prêt à l'emploi, vous pouvez en créer un vous-même via CustomValidator.
⑸ Cryptez et enregistrez le nom de connexion, le mot de passe et d'autres données de l'utilisateur. Chiffrer les données saisies par l'utilisateur puis les comparer avec les données enregistrées dans la base de données équivaut à « stériliser » les données saisies par l'utilisateur. Les données saisies par l'utilisateur n'ont plus de signification particulière pour la base de données, cela empêche donc. les attaquants d'injecter des commandes SQL. La classe System.Web.Security.FormsAuthentication possède un HashPasswordForStoringInConfigFile, qui est très approprié pour nettoyer les données d'entrée.
⑹ Vérifiez le nombre d'enregistrements renvoyés par la requête qui a extrait les données. Si le programme exige qu'un seul enregistrement soit renvoyé, mais que l'enregistrement effectivement renvoyé comporte plusieurs lignes, il sera traité comme une erreur.