Question:
Est-il possible de détecter 100% de SQLi avec une simple regex?
reed
2019-02-19 20:49:20 UTC
view on stackexchange narkive permalink

Je me demande s'il est possible de détecter 100% des attaques SQLi possibles en utilisant une simple regex.

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 détecté.")}  

Les questions sont:

  • Cette expression régulière interceptera-t-elle toutes les attaques SQLi possibles qui utilisent SELECT? Sinon, est-il possible de changer cette expression régulière pour qu'elle détecte toutes les injections qui reposent sur SELECT?
  • Est-il possible de changer cette expression régulière pour qu'elle capture tous les SQLi possibles, donc pas seulement les instructions SELECT mais aussi tout le reste? J'ai peur que, pour y parvenir, j'aie besoin d'ajouter chaque mot clé SQL possible à l'expression régulière, y compris "AND" et "OR".
  • Supposons que ce ne soit pas possible ou faisable pour détecter tous les SQLi en essayant de faire correspondre tous les mots-clés SQL possibles, y a-t-il un sous-ensemble limité de mots-clés qui me permettrait de détecter la grande majorité des attaques possibles?
@reed Le problème est que StackExchange n'est pas un forum ouvert pour discuter des idées.C'est un site de questions / réponses avec des restrictions sur les types de questions qui peuvent être posées, afin de promouvoir un contenu utile à la fois à ceux qui posent les questions * et * aux futurs lecteurs.Des questions comme celle-ci, où le but (prévu ou non) est de ruminer des idées plutôt que d'obtenir une seule réponse concrète, ne sont pas considérées comme étant sur le sujet ici.Puisque toute réponse correcte devrait commencer par "ne faites pas ceci, utilisez des paramètres à la place", il ne semble pas y avoir beaucoup de valeur qui puisse en découler.
@Polynomial, les questions que j'ai posées sont spécifiques.Attrape-t-il tous les SQLi qui utilisent SELECT?Oui, non, pourquoi?Je crois que ce genre de questions est ce qui se cache derrière la plupart des IDS.
À moins qu'il ne s'agisse d'une sorte d'exercice d'apprentissage / académique, je découragerais cette approche.Au lieu de détecter / analyser les entrées utilisateur, utilisez les mécanismes de base de données qui évitent sqli [instructions préparées par PHP] (http://php.net/manual/en/pdo.prepared-statements.php)
Non, un simple `preg_match (" / select / i ", $ input)` ne détectera PAS tous les sqli.Le mot-clé `SELECT` serait en effet un avertissement fort, mais il vous donnerait de faux positifs (par exemple un mot de passe contenant SELECT) et échouerait lorsque le sqli est ofuscated.
J'étais sûr qu'il y avait un double vers lequel je pourrais vous indiquer, mais je n'en ai jamais trouvé.Il devrait y en avoir un.
Pouvez-vous montrer comment `$ input` va être utilisé dans la requête, s'il vous plaît?
@schroeder https: // stackoverflow.com / questions / 1732348 / regex-match-open-tags-except-xhtml-self-contents-tags semble être un bon candidat
@bradbury9 Pour la détection d'intrusion (l'une des balises sur la question), je pourrais voir une vérification SQLi de base (regex ou autre) utilisée comme indicateur pour une activité suspecte qui conduit à une interdiction de compte / ip au lieu de l'ignorer parce que vous êtes SQLipreuve (via des déclarations préparées) et risquer un autre vecteur d'attaque que l'adversaire utilise fonctionnera avant de déclencher une interdiction.Quelque chose comme ça serait distinct de la protection de l'application contre SQLi où l'approche est, comme vous l'avez dit, complètement inappropriée.
Vous essayez d'analyser des informations sémantiques dans un langage récursif avec des expressions régulières?[Qu'essayez-vous de faire, invoquer Codethulu ou quelque chose comme ça?!?] (Https://stackoverflow.com/a/1732454/32914)
@reed Imaginez la frustration de vos utilisateurs de pour être frustrés de ne pas pouvoir soumettre de message / commentaire / biographie / quoi que ce soit en disant _ "Je vous recommande de sélectionner le meilleur outil pour le travail." _;)
Bien qu'il n'y ait pas de regex simple qui puisse le faire - et aucune regex ne peut le faire de manière totalement fiable - il existe toujours une industrie de plusieurs milliards de dollars basée sur cette idée: les pare-feu d'applications Web
Si vous êtes d'accord avec certains faux positifs, alors celui-ci capturera toujours toutes les injections SQL: `. *`
Vous n'avez même pas besoin d'une expression régulière, simplement «return true».Cependant, un taux de faux positifs assez élevé.
Convertissez simplement les chaînes de vos utilisateurs en hexadécimal.Au lieu de `select 'yeet'`, envoyez-le comme` select x'79656574'`
`J'ai peur que pour y parvenir, j'aie besoin d'ajouter tous les mots clés SQL possibles à l'expression régulière` yup, et puis certains
«SQLi» signifie-t-il «attaques par injection SQL»?Si oui, pourquoi ne dites-vous pas cela?
"Il a vaincu toutes les attaques par injection SQL avec une astuce simple! Les testeurs de pénétration le détestent!"
Sept réponses:
schroeder
2019-02-19 21:50:15 UTC
view on stackexchange narkive permalink

Le filtrage par 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 sur-ensemble de choses à filtrer (comme select et / ** / et substr et EXEC ), mais la liste devient alors très, très longue, et il se peut que vous n'obteniez toujours pas une liste complète.

La meilleure approche consiste à comprendre la gamme d'entrées acceptables et les protéger ou pour rendre inefficace l'utilisation de SQLi grâce à une conception appropriée.

Je suppose que c'est exactement le genre de réponse dont j'avais besoin, et ce lien est particulièrement utile pour comprendre à quel point tout cela peut devenir complexe.Merci.
Sans parler du taux de faux positifs.Plus il y a d'éléments dans votre liste, plus vous aurez de chances de faire correspondre quelque chose dans les données de la requête - nom, nom d'utilisateur, adresse e-mail, etc. Imaginez si quelqu'un essayait de s'inscrire en tant que bob@executiveselect.com ou quelque chose du genre.
@alex.forencich ... d'où le besoin de savoir ce qui est normal pour l'entrée ...
De plus, même si vous avez réussi à intercepter toutes les tentatives d'injection à l'aide de select, l'injection de fragments SQL * qui modifient les requêtes existantes pour faire autre chose alors qu'elles étaient censées le faire est probablement une classe d'attaques encore plus importante - et celles-ci n'ont pas de mot clé caractéristique.
@alex.forencich Et parfois, l'ensemble des données valides peut chevaucher l'ensemble des entrées malveillantes.https://xkcd.com/327/
"conception appropriée" Cela améliorerait * grandement * la réponse en mentionnant ce qu'est cette conception appropriée, la partie des requêtes paramétrées en particulier.
@jpmc26 Une conception appropriée, IMO, n'est pas appropriée en tant que question SE.C'est tellement vaste avec une telle quantité de matériel déjà publié que quiconque ne peut pas le comprendre ne devrait vraiment pas le faire du tout.
@Nelson Tout ce que le "matériel publié" se résume principalement à: "Utilisez des requêtes paramétrées pour toute valeur qui ne peut pas être codée en dur directement dans le texte de la requête, en particulier l'entrée utilisateur."(Littéralement. La seule chose au-delà de cela est la question de savoir quoi faire si vous avez besoin d'avoir une sorte de valeur dynamique pour un identifiant, et cela n'est pas nécessaire dans la grande majorité des cas.) L'inclusion d'unbref résumé de cette nature.Ce n'est vraiment pas un sujet aussi vaste que vous semblez le penser.
@jpmc26: Bien que l'utilisation de requêtes paramétrées soit la * procédure d'implémentation * que vous devez absolument suivre, je pense qu'il vaut la peine de comprendre * pourquoi * elle est intrinsèquement meilleure que la méthode proposée.La méthode proposée tente de repérer tout ce qui pourrait devenir dangereux lorsqu'il est analysé et évalué par le moteur de base de données, alors qu'avec les requêtes paramétrées, l'entrée utilisateur est vraisemblablement rendue impossible à analyser en premier lieu (en étant convertie, par exemple, en une chaîne littérale), tandis queen tenant compte des particularités syntaxiques spécifiques du moteur de base de données utilisé pour exécuter la requête.
De plus, cela n'attrape pas les attaques susceptibles de perturber le service, telles que `"; drop table users; --` qui, simplement, supprime la table des utilisateurs (hypothétiques). C'est beaucoup plus dévastateur.`";mettre à jour les utilisateurs set password = "";- ».
J'ajouterais à la réponse que "si vous avez un problème et que vous utilisez regex, vous avez deux problèmes maintenant".Fondamentalement, il veut échanger l'injection SQL contre l'injection Regex ... Avec cette approche, il pourrait rendre l'application vulnérable pour les deux problèmes en même temps, et Dieu sait ce qui pourrait être possible avec la combinaison de ces deux.
@Mateusz Je ne suis pas du tout d'accord avec votre déclaration.L'idée est de tester si une certaine chaîne correspond à l'expression régulière.Il n'y a rien venant du côté utilisateur, dans l'expression régulière.Juste la valeur à vérifier.Mais, oui, c'est encore 2 problèmes.
Considérez également combien il est plus simple d'utiliser simplement des bibliothèques standard pour sécuriser vos requêtes avec un paramétrage approprié.Sans oublier qu'ils ont pensé à beaucoup plus de cas extrêmes que nous, même les meilleurs d'entre nous.
`mais alors la liste devient très, très longue` - non, la liste serait littéralement * INFINIMENT LARGE *, de peur que vous ne considériez la longueur de requête maximale, qui dans MySQL est de 67 mégaoctets __BY DEFAULT__, mais même en considérant une longueur de requête maximale de 67MEGABYTES, la liste sera en effet * EXTRÊMEMENT * grande.
Sefa
2019-02-19 21:50:03 UTC
view on stackexchange narkive permalink

NON

Puisque chaque injection SQL est (par définition) du SQL valide et que SQL est un langage sans contexte ( source), il y a (encore une fois, par définition) aucune expression régulière capable de faire correspondre une injection SQL, et essayer de le faire donnerait probablement un résultat similaire à celui-ci.

Comme dit à peu près tous les commentaires, utilisez le bon outil pour le emploi. Dans ce cas, c'est une déclaration préparée.

Pour être pédant, cela signifie qu'une expression régulière qui correspond * uniquement * aux injections SQL (et à toutes) est impossible, ce qui est vrai mais pas de grande valeur - si elle devait jamais exister, une solution qui correspondrait également à un SQL invalide seraitd'accord, ce qui rouvre la question.Il ne s'agit bien sûr que d'un pinaillage théorique, en pratique les regex ne sont pas le bon outil ou la bonne approche pour le travail.
Un autre point noir théorique est que les regex modernes sont strictement plus puissantes que la définition originale de l'expression "régulière", en raison des lookarounds et des backreferences et autres.Je ne serais pas surpris si des expressions régulières plus modernes sont même complètes de Turing.
Cela ne suit pas.Chaque chaîne de 1 est une expression mathématique valide, et les expressions mathématiques sont un langage sans contexte, mais cela ne signifie pas que je ne peux pas écrire une expression régulière pour correspondre à des chaînes de 1.
Ce n'est pas correct, pour détecter SQLi vous ne détectez pas de syntaxe SQL valide, il vous suffit de détecter les constructions de contournement de devis.(Cependant, c'est toujours une approche très fragile)
@PedroA, même si théoriquement possible avec les regex modernes, serait trop complexe pour être pratique.
@GiulioMuscarello /.*/ correspond à tous les SQL valides (et aussi à certains SQL non valides), mais ne serait probablement pas ok :)
@immibis a raison.Par souci de simplicité, disons que nous définissons «SQL trop long» comme Ä instruction SQL de plus de 1000 caractères ». Il est évident que chaque« SQL trop long »est par définition un SQL valide, et il est évident que vous pouvez détecter un SQL trop long par unRegex trivial. Par la logique de cette réponse, ce serait impossible. Le défaut ici est qu'il est acceptable de donner des faux positifs sur SQL non valide.
@MSalters Alors, comment utiliseriez-vous votre regex «trivial» pour analyser correctement toute instruction SQL possible?Les langages réguliers ne permettent pas une imbrication et / ou une récursivité arbitraires, mais toute instruction SQL peut être imbriquée arbitrairement (par exemple `sélectionnez ceci à partir de là où (sélectionnez cela de là où (...)) jointure gauche (sélectionnez ...) ...; `).Je pense que les commentaires et certains des exemples que les gens affichent ici manquent du point général soulevé par la réponse, qui est en fait correcte.
@MSalters,, il y a deux parties dans votre définition de "SQL trop long": il doit s'agir d'une instruction SQL et elle doit comporter plus de 1000 caractères.Détecter que l'instruction comporte plus de 1000 caractères est simple pour une expression régulière, mais détecter qu'il s'agit de SQL est impossible.La lettre "Q" répétée 1001 fois est trop longue, mais ce n'est pas "SQL trop longue".
@Mark En fait, vous ne vous soucieriez pas que ce soit du SQL, mais simplement qu'il soit trop long.Le moteur SQL peut détecter s'il s'agit de SQL.
@immibis Ensuite, votre regex ne détecte pas "SQL trop long", juste des chaînes trop longues.La réponse pourrait peut-être être reformulée comme "il est impossible pour l'expression rationnelle de déterminer si une entrée donnée est SQL ou non" (et donc impossible d'exclure l'injection SQL tout en autorisant autre chose)
@mbrig: Ceci est typique d'un modèle théorique incorrect.La question est de savoir comment vous protéger contre l'injection SQL.Ces chaînes qui ne sont pas SQL par définition ne peuvent pas être une injection SQL, vous ne vous souciez donc pas des erreurs de classification dans ce sous-ensemble.Maintenant que nous avons 3 groupes (définitivement injection SQL, certainement pas, ne vous inquiétez pas) vous ne pouvez plus utiliser les résultats sur la classification binaire (appartient / n'appartient pas à un langage sans contexte)
@MSalters Je ne suis pas d'accord avec le fait que vous ne vous souciez pas des erreurs de classification non SQL.Vous devez clairement autoriser les non-SQL à avoir un filtre utile, sinon /.*/ et vous avez terminé.Je suis d'accord qu'il y a un peu de lacune logique, en ce que l'injection SQL est un sous-ensemble de SQL et pour être correct, vous devez démontrer une sorte d'équivalence dans la difficulté d'analyse.
Je crois comprendre que les langages sans contexte sont un sur-ensemble d'expressions régulières.Ainsi, toutes les expressions régulières sont des langages sans contexte, et certains, mais pas tous, les langages sans contexte sont (peuvent être reconnus par) des expressions régulières.Ainsi, il est possible que SQL soit à la fois sans contexte et reconnaissable par la bonne expression régulière, même si ce n'est peut-être pas le cas.
Les langages sans contexte (CF) @CJDennis sont un sur-ensemble _proper_ des langues régulières, c'est-à-dire qu'il y a des éléments dans l'ensemble des langues sans contexte qui ne sont pas membres de l'ensemble des langues régulières (RL).L'ensemble RL est un sous-ensemble _proper_ de CF.
Fake Name
2019-02-20 04:16:52 UTC
view on stackexchange narkive permalink

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

  • . + détectera effectivement tout possible SQLi.

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 pourriez é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 son objectif.

Utilisez des instructions préparées ou des requêtes paramétrées. Ils existent pour résoudre ce problème.

Techniquement correct est le meilleur type de correct .. mais pas dans ce scénario: P
@DanPantry - Rien dans la question ne spécifiait qu'il fallait * autoriser * quoi que ce soit.
Cela aurait peut-être dû être un commentaire plutôt qu'une réponse, mais il contient un bon point.Au lieu de se concentrer sur la façon de bloquer toutes les attaques, OP devrait se concentrer sur les chaînes légitimes qui doivent être autorisées.
Cette réponse pourrait être améliorée en mentionnant comment même l'expression rationnelle "select" causera beaucoup de fausses correspondances, pour tout texte contenant le mot "select".
@FakeName veuillez consulter l'historique des modifications de la question.Les faux positifs n'étaient pas à l'origine une préoccupation, mais sont devenus une préoccupation après de nombreuses discussions dans les commentaires.
Bien que je vois complètement ce que vous faites, le premier message est tout simplement faux (et les partisans audacieux ne sont pas visiblement ironiques sans lire).J'ai rencontré des développeurs dans ma vie qui voient quelque chose comme ça et ne lisent pas, créant une belle regex d'ailleurs parce que l'Internet le dit ...
@AnoE - Je ne peux pas empêcher les gens stupides d'être stupides.C'est comme ça que réside la folie.Si quelqu'un ne peut pas être dérangé de lire au-delà de l'en-tête, il est probablement déjà une cause perdue.En outre, ce n'est pas tout à fait faux, c'est littéralement correct (mais pas de la façon dont vous pourriez le penser).La désactivation d'une base de données * est * un moyen complètement fonctionnel d'empêcher SQLi, par exemple.Bien sûr, cela rend également la base de données inutile, mais tout éventuel SQLi sera évité.
J'aime cette réponse pour son essence: n'essayez pas de mettre sur liste noire les éventuelles requêtes d'attaque, utilisez plutôt une liste blanche de requêtes acceptables.Vous contrôlez ce qui peut être demandé à la base de données, assurez-vous d'appliquer ce contrôle en utilisant les meilleures pratiques ainsi qu'en validant et en nettoyant les entrées.
Cette réponse est une très bonne leçon sur le fonctionnement des listes noires: l'expression régulière `. +` Manque beaucoup d'injections SQL!`.` ne correspond pas aux nouvelles lignes par défaut.
D'un autre côté, si un système est correctement conçu, une requête qui ne correspond à rien bloquerait toutes les chaînes d'attaque SQLi possibles, car il n'y en aurait pas.
@Gilles: J'étais à moitié tenté d'essayer de trouver quelque chose que je pourrais appeler "une attaque SQLi" impliquant la chaîne vide, mais c'est un bon point.
@Gilles - Si vous pouvez produire une injection qui repose * uniquement * sur les nouvelles lignes, je serai impressionné.Notez que injections = / = une chaîne d'espaces qui dépasse cela.
Oh, `preg_match` est une recherche, pas une correspondance ancrée, je suppose?(Je ne suis pas familier avec PHP.) Avec une recherche, cela bloque tous les SQLi qui ne contiennent que des caractères imprimables.Il faut également s'inquiéter de la prise en charge appropriée des octets nuls, des points Unicode non valides et des encodages UTF-8 non valides: si le moteur regex s'étouffe sur l'un d'entre eux mais que le moteur SQL et le pipeline de communication les passent, il y a un risque.
@Gilles - La réponse supposait que c'était une fonction de recherche générale de regex, pas une implémentation spécifique.La syntaxe n'est pas correcte pour `preg_match` de toute façon.La question était "pouvez-vous utiliser des expressions régulières pour détecter SQLi", et non "pouvez-vous utiliser` preg_match` pour détecter SQLi ", j'ai donc répondu à la première.
Daniel Pryden
2019-02-21 20:21:15 UTC
view on stackexchange narkive permalink

Je me demande s'il est possible de détecter 100% des attaques SQLi possibles en utilisant une simple regex.

Le fait même que vous posiez la question Cela montre que vous pensez mal au problème.

L'injection SQL n'est pas une vulnérabilité dans les données . C'est une vulnérabilité dans le code de l'application 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 pouvez dire que ce que vous essayez de faire est de détecter les tentatives d'attaques par injection SQL. Mais maintenant, vous devez déterminer l ' intention de certaines entrées. Si je tape une apostrophe nue dans un champ, est-ce une faute de frappe ou une tentative d'attaque par injection SQL? Pouvez-vous détecter 100% de mes intentions ? Bien sûr que non.

Fondamentalement, tenter d'identifier des 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 considère que des données est soumise au mieux à un taux de faux positifs très élevé. Toute solution que vous concevez qui pourrait éventuellement 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. p>

"Ma réponse est-elle une attaque par injection SQL?"Eh bien, ça pourrait être;)
@ypercube: Eh bien, c'est peut-être une question de sémantique.Je dirais: cela * pourrait * déclencher un * effet * d'injection SQL, mais pour être une * attaque * d'injection SQL, l'effet devrait être malicieusement motivé.Et c'est un peu ce que je veux dire: si vous ne regardez que les données, vous ne pouvez pas le savoir avec certitude - au mieux, vous pouvez appliquer une heuristique, et une heuristique ne peut pas avoir une précision de 100%, par définition.
Philipp
2019-02-20 21:21:50 UTC
view on stackexchange narkive permalink

Non. Tout d'abord, il y a plusieurs choses maléfiques que vous pouvez faire avec les 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 commun nom d'utilisateur Robert '); DROP TABLE Etudiants; - . 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 une entrée qui correspond à / select / i , vous obtiendrez une tonne de faux positifs (16 faux positifs et en ne comptant que sur le site Web 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 celles de mySQL, toute autre API de base de données devrait fournir un fonction adaptée à cette syntaxe de base de données spécifique).

Mais lorsque vous essayez de vous protéger contre les injections SQL en bloquant certaines entrées, vous menez la bataille sur la mauvaise ligne de front. Il serait beaucoup plus intelligent de se défendre contre les injections SQL en arrêtant de créer des instructions SQL par concaténation de chaînes. Les autres moyens courants d'interagir avec les bases de données d'une manière qui rend les injections SQL difficiles à écrire involontairement sont:

  • Utilisez un wrapper ORM qui écrit des requêtes SQL pour vous
  • Utilisez des requêtes paramétrées (également appelées instructions préparées)
  • Utiliser un langage de programmation où SQL fait partie de la syntaxe du langage
  • Utiliser des procédures stockées
Les requêtes paramétrées ne sont pas «également appelées» instructions préparées.Les requêtes paramétrées sont une forme d'une instruction préparée, mais pas la seule.Les deux ne doivent pas être confondus.
Les wrappers ORM sont notoirement mauvais pour créer du SQL efficace et bien formé.Je mettrais cela à la * fin * de vos recommandations, si je les ajoutais même à la liste.
@MaxVernon - Les ORM produisent un code clair et concis, ce qui 90% du temps est plus important que de tirer des performances supplémentaires de la base de données.
@paj28 - c'est peut-être le cas, mais lorsque vous utilisez un ORM pour écrire du SQL à votre place, vous rendez presque impossible le dépannage des performances plus tard, quand cela * importe *.Les ORM sont des raccourcis qui ont tendance à vous tirer dans le pied lorsque vous vous y attendez le moins.Si vous êtes du tout préoccupé par l'écriture d'un bon code, vous écrivez le SQL vous-même.
En fait, @paj28, je ne suis pas d'accord avec le fait que les ORM permettent un code clair et concis.Ce qu'ils font réellement est sans doute le code le plus important de tout le projet.Autrement dit, si vous pensez que les données sont la raison d'être du projet en premier lieu.
Que vous aimiez ou non les ORM est une question de génie logiciel, pas une question de sécurité.
luis.espinal
2019-02-20 19:13:07 UTC
view on stackexchange narkive permalink

Non. Une implémentation de regexp est typiquement un langage régulier (ou une extension de celui-ci qui permet l'analyse de certaines grammaires non régulières.)

SQL d'autre part, c'est fermement un langage sans contexte non régulier. Ergo, il ne peut pas être analysé par une expression rationnelle en langage régulier.

Si vous deviez utiliser une extension d'expression régulière qui utilise le regroupement, vous pourrez peut-être analyser du SQL valide, mais aussi du SQL invalide ou des choses qui pourraient ressembler à du SQL mais qui ne le sont pas.

La meilleure chose à être sûr est d'utiliser une grammaire sans contexte qui exprime le dialecte SQL que vous recherchez, si vous vouliez vraiment détecter une attaque par injection SQL.

ps. Mon opinion personnelle est que l’un des meilleurs moyens d’éviter ou de minimiser les attaques par injection SQL est de ne jamais invoquer du SQL brut depuis l’application (en s’appuyant plutôt sur des procédures stockées, qui elles-mêmes nettoient leurs arguments.)

de la graisse de coude, et pas nécessairement 100% résistante aux injections de fer. Mais cela fonctionne très bien. Caveat emptor évidemment, car d'autres développeurs pourraient avoir des expériences différentes avec une telle approche.

SQL est un "langage sans contexte non régulier".Cela va avoir besoin d'explications car cela semble faux à première vue.
Euh non.Pour commencer, SQL a été décrit plusieurs fois en BNF, par exemple, c'est un langage sans contexte.Voici un exemple: https://docs.oracle.com/cd/B28359_01/server.111/b28286/ap_syntx002.htm
De plus, SQL n'est ni une grammaire régulière droite ni une grammaire régulière gauche.En fait, il n'y a pas de grammaire régulière qui puisse capturer `SELECT x from y` où` x` ou `y` sont des instructions SQL SELECT elles-mêmes.
Puisque nous avons établi que SQL est sans contexte (car il peut être représenté en BNF) et qu'il n'est pas régulier (car une grammaire régulière ne peut pas capturer la récursivité), nous pouvons conclure que SQL est un langage sans contexte non régulier.Après tout, toutes les grammaires régulières sont sans contexte, mais toutes les grammaires sans contexte ne sont pas régulières.
Vous semblez aller de l'avant dans certains concepts.Comment arriver à "sans contexte" à partir de "peut être décrit dans BNF"?Je pense que vous apportez des volumes d'autres concepts sans les expliquer (ou en supposant qu'ils sont vrais).Bien que je n'essaie pas d'affirmer que quelque chose d'autre est vrai, votre réponse ne montre pas clairement en quoi vos affirmations sont vraies.Pouvez-vous relier quelques points?
J'utilise des définitions de manuels: une grammaire (dans ce cas SQL) décrite dans BNF est une grammaire sans contexte.Et comme il contient de la récursivité (voir l'exemple précédent que j'ai mentionné), il ne peut pas être accepté par un automate fini non déterministe ou NFA.Et cela, par définition, est un langage non régulier.
C'est moi qui relie les points en utilisant des définitions de grammaire formelle standard.Si je me trompe, faites-le remarquer.Tout ce qui va au-delà de cela nous obligera à visiter un manuel ou à faire une sorte de preuve formelle.
Grande différence entre avoir raison et être utile.Cette réponse n'est pas utile sans que le lecteur se penche sur plusieurs concepts informatiques pour commencer à comprendre ce que vous faites.Je vous demande de modifier la réponse pour relier quelques points pour rendre cette réponse plus utile.
Pour être honnête, les attaques par injection SQL ne sont pas nécessairement du SQL valide.(Une fois qu'ils sont placés dans le reste de la requête, ils le sont.) À cause de cela, ce n'est pas un problème si nous pouvons ou ne pouvons pas détecter SQL valide avec regex.
Un langage non CF peut avoir une grammaire lexicale régulière, vous n'avez donc pas besoin de faire correspondre toute la grammaire SQL.Identifiez simplement les chaînes qui pourraient briser les limites des jetons lorsqu'elles sont interpolées dans une séquence existante de jetons. Cela dit, je suis d'accord avec toutes les affiches qui ont souligné que les filtres ont un mauvais bilan par rapport à la sécurité par construction.
"Grande différence entre avoir raison et être utile."C'est un argument différent de celui que vous avez dit à l'origine (que ce que j'ai dit semblait faux à première vue.) C'est malhonnête et malhonnête.Je ne suis pas intéressé à me lancer dans une dispute qui a commencé par la malhonnêteté.De plus, ma réponse n'est pas la seule à s'intéresser aux grammaires sans contexte.Alors vissez ça.Votez contre le tout ou demandez à quelqu'un d'autre de modifier ou de supprimer complètement la réponse.Je suis d'accord avec l'un ou l'autre.
@luis.espinal votre réponse est irrationnelle et motivée par les émotions.Il n'y a pas eu de malhonnêteté.Veuillez comprendre que vous avez "la malédiction de la connaissance" et que vous devez être capable d'expliquer des concepts à des personnes qui n'ont pas entendu les définitions ou les concepts que vous utilisez.Ce n'est pas un site pour que les gens montrent les «bonnes réponses».Il s'agit d'un site de questions-réponses, ce qui, de par sa nature même, signifie que les réponses doivent non seulement être aussi correctes que possible, mais également comprises par les personnes qui pourraient à peine comprendre leurs propres questions.
@luis.espinal Je n'ai aucune idée de la raison pour laquelle vous devenez à la fois émotif et réticent à simplement *** modifier votre réponse pour expliquer ce que vous voulez dire ***.Si vous voyez le besoin de vous expliquer comme un défi à votre capacité à connaître la bonne réponse, alors vous devez repenser vos motivations pour y répondre.
Compte tenu de l'autre côté du concept, "bien sûr, ce n'est pas recommandé", je peux également créer une expression régulière capable de bloquer 100% de la variété de requêtes, donc cette réponse ne peut pas être "non".J'ai eu un cas où un gestionnaire était capable de stocker de nouvelles requêtes en tant que varchar, alors les clients ont pu en remplir une partie, la méthode ORM "params" ne permettra jamais ce genre de processus.
sumit_suthar
2019-12-31 12:05:07 UTC
view on stackexchange narkive permalink

Non, votre application ne sera pas sécurisée à 100% si vous utilisez une correspondance de modèle ou une expression régulière pour identifier l'attaque par injection SQL. Vous serez confronté à une détection manquée de SQLI si vous utilisez ce type d'approche. La meilleure façon d'obtenir une protection à 100% consiste à utiliser l'autoprotection des applications d'exécution (RASP) dans votre application. En cas de pare-feu d'application Web (WAF), vous obtiendrez de faux résultats négatifs.



Ce Q&R a été automatiquement traduit de la langue anglaise.Le contenu original est disponible sur stackexchange, que nous remercions pour la licence cc by-sa 4.0 sous laquelle il est distribué.
Loading...