Je me demande s'il est possible de détecter 100% des attaques SQLi possibles à l'aide d'une expression régulière simple.
En d'autres termes, en utilisant un code PHP très simple comme exemple:
if (preg_match("/select/i", $input)) {
attack_log("Possible SELECT SQLi detected.")
}
Les questions sont:
Le filtrage de mots clés pour SQLi n'est pas une bonne technique. Il y a trop de façons de le contourner.
Des choses folles comme sel/**/ect
Pourraient fonctionner, par exemple. Ou jouer à des jeux avec substr()
. Et puis il y a EXEC('SEL' + 'ECT 1')
.
Il existe de nombreux guides sur la façon de contourner les techniques de filtrage courantes.
Mais alors vous pourriez demander s'il y a un surensemble de choses à filtrer (comme select
et /**/
Et substr
et EXEC
), mais alors la liste devient très, très longue, et vous pourriez ne pas toujours obtenir une liste complète.
La meilleure approche consiste à comprendre la gamme des entrées acceptables et à protéger celles-ci ou à rendre inefficace l'utilisation de SQLi grâce à une conception appropriée.
Étant donné que chaque injection SQL est (par définition) un SQL valide et que SQL est un langage sans contexte ( source ), il n'y a (encore une fois, par définition) aucune expression rationnelle capable de correspondre à une injection SQL et d'essayer cela donnerait probablement un résultat similaire à this .
Comme le disent à peu près tous les commentaires, utilisez le bon outil pour le travail. Dans ce cas, c'est une déclaration préparée.
.+
Détectera en effet tout SQLi possible .Cependant, il détectera également toute tentative de faire des requêtes normales (ou tout texte du tout), rendant la base de données complètement inutile .
Vous pouvez également dire que la désactivation de la base de données protège de SQLi. C'est vrai, mais cela rend également la base de données inutile pour l'usage auquel elle est destinée.
Utilisez des instructions préparées ou des requêtes paramétrées. Ils existent pour résoudre ce problème.
Je me demande s'il est possible de détecter 100% des attaques SQLi possibles à l'aide d'une expression régulière simple.
Le fait même que vous posiez la question de cette façon montre que vous pensez mal au problème.
L'injection SQL n'est pas une vulnérabilité dans données. C'est une vulnérabilité dans l'application code qui gère ces données.
Par exemple: en ce moment, je tape une "injection SQL" dans une zone de texte sur un site Web! Et je peux taper quelque chose comme '- DROP TABLE Users; ici! Ma réponse est-elle une attaque par injection SQL? Bien sûr que non.
Maintenant, vous pourriez faire valoir que ce que vous essayez de faire est de détecter tenté les attaques par injection SQL. Mais maintenant, vous devez déterminer le intention d'une entrée. Si je tape une apostrophe nue dans un champ, s'agit-il d'une faute de frappe ou d'une tentative d'injection SQL? Pouvez-vous détecter 100% de mes intentions? Bien sûr que non.
Fondamentalement, tenter d'identifier les attaques possibles signifie que votre taux de détection ne peut jamais être de 100%.
Puisqu'une vulnérabilité d'injection SQL n'existe que dans le code, et non dans les données, toute analyse qui ne prend en compte que les données est soumise au mieux à un taux de faux positifs très important. Toute solution que vous imaginez et qui pourrait correspondre à tout le trafic d'attaque réel interpréterait également une très grande quantité de trafic légitime vers ce site Web et bien d'autres, comme des "attaques" lorsqu'aucune attaque de ce type n'était prévue.
Non. Tout d'abord, il y a plusieurs mauvaises choses que vous pouvez faire avec des injections SQL qui ne nécessitent pas l'utilisation du mot-clé SELECT, comme le tristement célèbre mot de passe universel ' OR '1' = '1
ou le nom d'utilisateur courant Robert'); DROP TABLE Students;--
. En outre, "sélectionner" est un mot très courant dans la langue anglaise qui peut apparaître de manière complètement bénigne dans toutes sortes de contextes différents. Donc, si vous filtrez toute entrée qui correspond à /select/i
vous allez obtenir une tonne de faux positifs (16 faux positifs et en comptant uniquement sur le site que vous lisez en ce moment, par exemple).
Si vous souhaitez nettoyer les entrées avant d'envoyer des données à votre base de données, alors PHP a une fonction pratique à cet effet (ce sont ceux pour mySQL, toute autre API de base de données devrait fournir une fonction similaire adaptée à cette base de données spécifique syntaxe).
Mais lorsque vous essayez de vous protéger contre les injections SQL en bloquant certaines entrées, vous livrez la bataille sur la mauvaise ligne de front. Il serait beaucoup plus intelligent de se défendre contre les injections SQL en s'arrêtant pour créer des instructions SQL par concaténation de chaînes. Les autres façons courantes d'interagir avec les bases de données d'une manière qui rendent les injections SQL difficiles à écrire involontairement sont: