web-dev-qa-db-fra.com

Est-il possible de détecter 100% de SQLi avec une simple expression régulière?

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:

  • Cette expression régulière interceptera-t-elle toutes les attaques SQLi possibles utilisant SELECT? Si ce n'est pas le cas, est-il possible de changer cette expression régulière afin qu'elle détecte toutes les injections qui dépendent de SELECT?
  • Est-il possible de changer cette expression régulière pour qu'elle attrape tous les SQLi possibles, donc non seulement les instructions SELECT mais aussi tout le reste? Je crains que pour y parvenir, j'aurais besoin d'ajouter chaque mot-clé SQL possible à l'expression régulière, y compris "ET" et "OU".
  • En supposant qu'il n'est pas possible ou faisable de détecter tous les SQLi en essayant de faire correspondre tous les mots clés SQL possibles, existe-t-il un sous-ensemble limité de mots clés qui me permettrait de détecter la grande majorité des attaques possibles?
37
reed

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.

169
schroeder

NON

É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.

106
Sefa

Techniquement , cela est tout à fait possible (bien que cela rende également la base de données inutile):

  • .+ 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.

58
Fake Name

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.

23
Daniel Pryden

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:

  • Utilisez un wrapper ORM qui écrit des requêtes SQL pour vous
  • Utiliser des requêtes paramétrées (également appelées instructions préparées)
  • Utilisez un langage de programmation où SQL fait partie de la syntaxe du langage
  • Utiliser des procédures stockées
9
Philipp