Question:
Pourquoi les procédures stockées et les instructions préparées sont-elles les méthodes modernes préférées pour empêcher l'injection SQL sur la fonction de chaîne d'échappement réelle mysql ()
Damien Pham
2020-04-21 06:45:59 UTC
view on stackexchange narkive permalink

Pourquoi les procédures stockées et les instructions préparées sont-elles les méthodes modernes préférées pour empêcher l'injection SQL sur la fonction mysql_real_escape_string () ?

Les commentaires ne sont pas destinés à une discussion approfondie;cette conversation a été [déplacée vers le chat] (https://chat.stackexchange.com/rooms/107110/discussion-on-question-by-damien-pham-why-are-stored-procedures-and-prepared-sta).
Douze réponses:
multithr3at3d
2020-04-21 07:58:19 UTC
view on stackexchange narkive permalink

Le problème de l'injection SQL est essentiellement le mélange de logique et de données, où ce qui devrait être des données est traité comme logique. Les instructions préparées et les requêtes paramétrées résolvent en fait ce problème à la source en séparant complètement la logique des données, de sorte que l'injection devient presque impossible. La fonction d'échappement de chaîne ne résout pas réellement le problème, mais elle essaie d'éviter les dommages en échappant à certains caractères. Avec une fonction d'échappement de chaîne, aussi bonne soit-elle, il y a toujours le souci d'un cas de bord possible qui pourrait permettre à un caractère non échappé de passer.

Un autre point important, comme mentionné dans @ Sebastian's commentaire, c'est qu'il est beaucoup plus facile d'être cohérent lors de l'écriture d'une application à l'aide d'instructions préparées. L'utilisation d'instructions préparées est d'une architecture différente de l'ancienne méthode classique; au lieu de la concaténation de chaînes, vous construisez des instructions en liant des paramètres (par exemple PDOStatement :: bindParam pour PHP), suivis d'une instruction d'exécution distincte (PDOStatement :: execute). Mais avec mysql_real_escape_string () , en plus d'exécuter votre requête, vous devez vous rappeler d'appeler cette fonction en premier. Si votre application a 1000 points de terminaison qui exécutent des requêtes SQL mais que vous oubliez d'appeler mysql_real_escape_string () ne serait-ce que sur l'un d'entre eux, ou si vous le faites de manière incorrecte, toute votre base de données pourrait être laissée grande ouverte.

En effet.Même sans se soucier de SQLi, les requêtes préparées représentent une séparation appropriée des préoccupations.
L'autre point est qu'il suffit d'oublier d'appeler `mysql_real_escape_string ()` une fois, et votre base de données est grande ouverte.L'utilisation de sprocs et d'instructions préparées est généralement une proposition architecturale du tout ou rien - soit vous le faites partout, soit nulle part.
Mais c'est aussi une des raisons pour lesquelles vous devriez utiliser une fonction wrapper pour vos requêtes, plutôt que d'exécuter directement des requêtes sur la base de données.
@SebastianLenartowicz Un mauvais développeur qui jette le code avec `mysql_real_escape_string` ouvrira largement la base de données s'il oublie de l'appeler une fois.Il est absolument possible et même pas compliqué d'écrire une couche d'abstraction qui a une interface similaire à PDO, en utilisant des espaces réservés nommés pour les valeurs, et une seule `mysql_real_escape_string` appelée si nécessaire.
Il convient de noter que les procédures stockées en soi ne sont pas une protection contre SQLi, car: 1. bien qu'elles soient moins naturelles, elles peuvent toujours créer des requêtes par concaténation de chaînes à l'intérieur, puis les exécuter, puis elles sont ouvertes au même typedes problèmes et 2. vous devez toujours émettre l'instruction sql pour les appeler et cette requête elle-même peut être vulnérable à l'injection si vous n'utilisez pas la liaison de paramètres.
@GodsBoss Sauf si ce que vous faites est vraiment trivial, essayer d'écrire votre propre couche d'abstraction DB est généralement un exercice dans les cas de bord manqués et "oh, ça ne le fait pas déjà; piratons-le".Les bibliothèques standard / ORM tiers existent pour une raison - vous n'avez donc pas à écrire les vôtres et à vous inquiéter pour toujours si vous avez manqué un cas.
Je suis d'accord, c'est pourquoi il y a tant d'ORM célèbres (comme Hibernate ou Doctrine for isntance) dans différentes langues: ils utilisent des requêtes paramétrées, sont souvent bien maintenues par des gens qui savent ce qu'ils font.Dans la plupart des cas, bien utiliser ces fonctions ORM couvre 99,99% du travail autour de SQLi.Ofc, il y a toujours un risque, que tout ne soit pas totalement assaini, d'être trompé par un jeune pirate soviétique qui a découvert que l'utilisation d'un jeu de caractères spécifique peut être interprétéedifféremment et générer une altération d'entrée (exemple totalement aléatoire), ou avoir une ancienne version de base de données vulnérable
Je ne sais pas à propos de PHP mais je sais qu'en Java, une instruction préparée peut permettre à une requête répétée de ne devoir être compilée qu'une seule fois, ce qui peut améliorer considérablement les temps d'exécution - dans de nombreux cas, c'est une micro-optimisation, mais dans d'autres, c'est la différence entre uneserveur et un serveur bloqué.
halfer
2020-04-21 15:53:52 UTC
view on stackexchange narkive permalink

Je pense que la question principale ici est de savoir pourquoi l'échappement de chaîne n'est pas aussi bon que les autres méthodes.

La réponse est que certains cas de bord permettent aux injections de passer même si elles sont échappées. Stack Overflow a plusieurs exemples ici.

Jefrey Sobreira Santos
2020-04-21 19:17:43 UTC
view on stackexchange narkive permalink

Bien que vous puissiez rester en sécurité en vous protégeant contre les entrées utilisateur qui échappent à SQLi, il est important de noter que cela peut ne pas toujours être suffisant. Dans ce terrible exemple, les guillemets ne sont jamais nécessaires pour réussir une injection SQL, malgré l'échappement:

  <? Php / * Ceci est un exemple de mauvaise pratique pour plusieurs raisons. Ce code ne doit jamais être utilisé en production. * / $ Post_id = mysql_real_escape_string ($ _ GET ['id']); $ qry = mysql_query ("SELECT title, text FROM posts WHERE id = $ post_id"); $ row = mysql_fetch_array ( $ qry); echo '<h1>'. $ row ['title']. '< / h1>'; echo $ row ['text'];  

Maintenant, que se passerait-il si on visitait .php? id = -1 + UNION + ALL + SELECT + 1, version () ? Voyons comment la requête se déroule:

  SELECT title, text FROM posts WHERE id = -1 UNION ALL SELECT 1, version ()  

Bien sûr qu'il y en a d'autres façons de résoudre ce problème (par exemple, en utilisant des guillemets et des échappements ou des int-cast), mais l'utilisation d'instructions préparées est un moyen de rester moins enclin à manquer ces choses et de laisser le pilote se soucier de la manière d'inclure les entrées de l'utilisateur dans la requête (même parce que , bien que cet exemple semble si facile à corriger, il existe des injections SQL à plusieurs niveaux qui consistent essentiellement à enregistrer des parties de la requête SQL dans la base de données en sachant que les données de la base de données seront utilisées à l'avenir dans le cadre d'une autre requête) .

Mieux vaut prévenir que guérir.

Machavity
2020-04-21 19:16:55 UTC
view on stackexchange narkive permalink

Parce que vous faites le même travail pour une meilleure sécurité

Un trope commun mentionné contre PHP est mysqli_real_escape_string () (regardez combien de temps il est! Can ' sont-ils cohérents avec la nomenclature?), mais la plupart des gens ne réalisent pas que l'API PHP appelle simplement l'API MySQL. Et que fait-elle?

Cette fonction crée une chaîne SQL légale à utiliser dans une instruction SQL

En d'autres termes, lorsque vous utilisez ceci , vous demandez à MySQL de nettoyer la valeur pour qu'elle soit «sûre» à utiliser dans SQL. Vous demandez déjà à la base de données de travailler pour vous à cet égard. L'ensemble du processus ressemble à ceci

  1. Échapper les données non fiables
  2. Assemblez la requête SQL finale (c'est-à-dire mettez les données échappées dans le SQL)
  3. Parse la requête
  4. Exécuter la requête

Lorsque vous utilisez une instruction préparée, vous dites à votre base de données qu'elle doit le faire dans un ordre différent

  1. Analyser la requête avec des espaces réservés
  2. Envoyez les données pour remplir les espaces réservés, en spécifiant le type de données au fur et à mesure
  3. Exécuter la requête
  4. Parce que nous envoyons les données séparément, nous faisons le même travail que l'échappement, mais nous bénéficions de ne pas avoir de données non fiables dans notre SQL . En tant que tel, le moteur ne peut jamais confondre les données fournies avec les instructions SQL.

    Il y a aussi un avantage caché ici. Ce que vous ne réalisez peut-être pas, c'est qu'une fois l'étape 1 terminée, vous pouvez répéter les étapes 2 et 3 encore et encore, à condition qu'elles aient toutes besoin d'exécuter la même requête, juste avec des données différentes.

      $ prep = $ mysqli->prepare ('INSERT INTO visites_log (nom_surviste, id_survité) VALUES (?,?)'); $ prep->bind_param ('si', $ nom_tilisateur, $ identifiant_touriste); // cette fonction passe par referenceforeach ($ _ POST ['guest_list'] comme $ visiteur_id = > $ nom_touriste) $ prep->execute ();  

    Cette requête a l'avantage de n'avoir qu'à boucler sur les données et à les envoyer encore et encore, plutôt que d'ajouter la surcharge d'analyse à chaque fois.

Je considère cela comme un échec de la conception du protocole filaire, ne pas séparer complètement le code et les données.OTOH, en utilisant des paramètres de liaison, la même API de bibliothèque cliente pourrait avoir son backend modifié silencieusement pour utiliser un nouveau et meilleur protocole filaire futur qui * fait * garder les choses hors bande plutôt que d'essayer d'effectuer des échappements.
Bonne réponse.Cependant, de nombreux pilotes de base de données implémentent des instructions préparées en échappant côté client.Je ne dis pas que c'est une bonne chose, mais vous pouvez voir que c'est courant dans la pratique si vous regardez le code source de divers connecteurs Python DBAPI.
Il y a aussi l'avantage de la mise en cache des plans dans les bases de données comme Oracle pour les instructions exécutées avec des valeurs différentes mais la même structure (attention à la vue des liaisons).
@paj28 PDO (qui couvre toutes les bases de données) effectue une préparation simulée, mais mysqli ne le fait pas
Anonymous
2020-04-21 20:01:55 UTC
view on stackexchange narkive permalink

Une bonne raison de ne pas utiliser mysql_real_escape_string : il est déconseillé

mysql_real_escape_string

(PHP 4> = 4.3.0, PHP 5)

mysql_real_escape_string - Échappe les caractères spéciaux d'une chaîne pour une utilisation dans une instruction SQL

Avertissement

Cette extension est obsolète en PHP 5.5.0, et il a été supprimé dans PHP 7.0.0. À la place, l'extension MySQLi ou PDO_MySQL doit être utilisée. Voir aussi MySQL: choisir un guide d'API et FAQ associée pour plus d'informations. Les alternatives à cette fonction incluent:

  mysqli_real_escape_string () PDO :: quote ()  

Source: mysql_real_escape_string

La doc explique également que l'échappement dépend du jeu de caractères :

Le jeu de caractères doit être défini soit au niveau du serveur, ou avec la fonction API mysql_set_charset () pour qu'elle affecte mysql_real_escape_string (). Voir la section des concepts sur les jeux de caractères pour plus d'informations.

Je dois également ajouter que les procédures stockées ne sont pas toujours «sûres», par exemple lorsqu'elles contiennent du SQL dynamique ... elles ne protègent pas contre les mauvaises pratiques de codage. Mais en effet, vous devriez utiliser des instructions paramétrées , c'est à vous de décider si vous souhaitez utiliser des procédures stockées.

"Parce que c'est obsolète" est un peu un raisonnement circulaire, car l'OP demande déjà pourquoi il a été abandonné ...
Cela ne répond pas aux raisons pour lesquelles les déclarations préparées sont préférées.L'ensemble de la bibliothèque PHP mysql était obsolète au profit de mysqli ou PDO, pas seulement `mysql_real_escape_string`.mysqli et PDO ont des fonctions exactement équivalentes.Ils appellent tous [la même fonction C sous-jacente] (https://dev.mysql.com/doc/refman/8.0/en/mysql-real-escape-string.html).
paj28
2020-04-21 20:25:09 UTC
view on stackexchange narkive permalink

Quelques bonnes réponses déjà, et je vais apporter quelques précisions supplémentaires:

Échapper

mysql_real_escape_string peut être utilisé en toute sécurité. Le conseil avec l'échappement est d'utiliser la fonction d'échappement adaptée à votre base de données . Vous avez besoin d'une fonction légèrement différente pour chaque base de données. La plupart des problèmes de sécurité subtils proviennent de personnes utilisant leur propre désinfectant (par exemple, simplement ' -> ' ') et ne réalisant pas les cas de coin. Vous devez toujours utiliser correctement mysql_real_escape_string , en mettant la valeur entre guillemets, mais cela (le principe, pas les guillemets) est vrai pour la plupart des défenses, y compris les déclarations préparées.

Instructions préparées

Les instructions préparées sont un très bon moyen d'arrêter l'injection SQL. Cependant, vous pouvez toujours vous tromper, j'ai parfois vu des gens construire dynamiquement une instruction SQL et construire une instruction préparée à partir de cela. Ils ont été très bouleversés quand nous leur avons dit que ce n'était toujours pas sûr, car nous leur avions dit d'utiliser des déclarations préparées! De plus, le code avec lequel vous vous retrouvez avec des instructions préparées est un peu désagréable. Pas vraiment, mais juste légèrement discordant sur le plan esthétique.

Certains connecteurs de base de données implémentent des instructions préparées en utilisant l'échappement en interne (je pense que psychopg pour Python / Postgres fait cela). Avec d'autres bases de données (Oracle en est une), le protocole prend en charge spécifiquement les paramètres, ils sont donc complètement séparés de la requête.

Procédures stockées

Les procédures stockées n'interrompent pas nécessairement l'injection SQL. Certains connecteurs vous permettent de les appeler directement comme une instruction préparée. Mais ils sont souvent appelés à partir de SQL, où vous devez toujours transmettre des données en toute sécurité dans SQL. Il est également possible qu'une procédure stockée ait une injection SQL en interne, c'est donc dangereux même lorsqu'elle est appelée avec une instruction préparée. Je pense que ce conseil découle principalement de la confusion. Les responsables de la sécurité ne sont généralement pas des DBA et sont vagues sur la différence entre les instructions préparées, les requêtes paramétrées (un autre nom pour les instructions préparées) et les procédures stockées (quelque chose de différent). Et ce conseil a persisté car les procédures stockées présentent certains avantages en matière de sécurité. Ils vous permettent d'appliquer la logique métier au niveau de la base de données, soit pour permettre un accès direct sécurisé à la base de données, soit comme mécanisme de défense en profondeur.

Saisissez une syntaxe de requête sûre

La façon dont je recommande d'arrêter l'injection SQL est d'utiliser un mécanisme de requête de type sécurisé. Il y en a beaucoup, y compris la plupart des ORM (Hibernate, SQLAlchemy, etc.) ainsi que certaines bibliothèques / fonctionnalités non ORM comme LINQ ou jOOQ. Ceux-ci protègent contre l'injection SQL, fournissent un bon code esthétique, et il est également plus difficile de les utiliser de manière incorrecte et de se retrouver avec une injection SQL. Personnellement, je suis un grand fan des ORM, mais tout le monde ne l'est pas. Pour la sécurité, le point clé n'est pas que vous utilisez un ORM, mais que vous utilisez un système de requête de type sécurisé.

Ok, j'espère que cela clarifie les choses pour vous. Bonne question.

Une autre façon dont les déclarations préparées peuvent mal tourner est qu'il y a des cas où cela est nécessaire mais non applicable.Par exemple, une instruction préparée ne vous permettra pas de paramétrer le nom d'une table ou d'une colonne.Si vous devez changer le nom de la table / colonne en fonction de l'entrée de l'utilisateur, les instructions préparées ne vous aideront pas.Vous devez vous rabattre sur un nettoyage correct des entrées utilisateur (de préférence avec une liste blanche de valeurs autorisées) et insérer des données directement dans la requête.C'est un cas limite facile à manquer lorsque vous travaillez avec des instructions préparées.
@ConorMancone - Bon point.Vous pouvez trouver ce [problème SQLAlchemy] (https://github.com/sqlalchemy/sqlalchemy/issues/4481) intéressant.
Qu'entendez-vous par "le code avec lequel vous vous retrouvez avec des instructions préparées est un peu désagréable"?
@Schwern - Juste que ça n'a pas l'air bien, surtout avec des requêtes complexes.Au lieu d'introduire des données là où elles sont utilisées, vous avez un?comme espace réservé et une ligne ultérieure qui attache les données.Moins mauvais avec les paramètres nommés.
Erik A
2020-04-21 23:02:04 UTC
view on stackexchange narkive permalink

Un argument supplémentaire, non-InfoSec, est que les paramètres permettent potentiellement des requêtes plus rapides et moins d'utilisation de la mémoire.

En utilisant les paramètres, les données et la requête sont séparées, ce qui est particulièrement important lors de l'insertion de très grandes chaînes et champs binaires (la chaîne entière doit être traitée par la fonction d'échappement (qui l'étend et peut nécessiter la copie de la chaîne entière), puis à nouveau analysée par le moteur SQL, alors qu'un paramètre doit simplement être passé et non analysé) .

Certains connecteurs de base de données permettent également le découpage avec des paramètres, ce qui évite d'avoir à avoir la chaîne entière en mémoire à la fois. La segmentation à l'aide de la concaténation de chaînes n'est jamais une option, car les données font partie de la chaîne SQL et donc la chaîne SQL ne peut pas être analysée sans elle.

Comme il n'y a aucun avantage à utiliser la concaténation de chaînes avec une fonction d'échappement sur l'utilisation de paramètres, et il y en a plusieurs pour l'utilisation de paramètres sur la concaténation de chaînes, il est logique que nous poussions vers les paramètres. Cela a conduit à la dépréciation des fonctions d'échappement, ce qui introduit des problèmes de sécurité potentiels à l'avenir, ce qui renforce la nécessité de ne pas les utiliser.

jmoreno
2020-04-22 08:20:30 UTC
view on stackexchange narkive permalink

Les procédures stockées et les instructions préparées limitent la portée potentielle en utilisant des paramètres. call GetUserWithName ('jrmoreno'); offre moins d’opportunité de jouer avec la requête, pas aucune opportunité. Notez que les procédures stockées paramétrées via des instructions préparées offrent encore moins call GetUserWithName (@userName); que les procédures stockées simples.

De plus, l'utilisation de procédures stockées vous ouvre à un autre type de injection sql: sql dynamique dans la procédure stockée.

Quant à savoir pourquoi utiliser des instructions préparées, les instructions préparées sont un protocole binaire où les paramètres ont des types et des tailles fixes. Lorsqu'il est traité par le serveur, il est impossible pour un nombre d'être autre chose qu'un nombre ou pour une chaîne de s'étendre au-delà de ses limites et d'être traitée comme plus de commandes sql (tant que cette chaîne n'est pas utilisée pour créer un sql dynamique à l'intérieur le moteur sql).

Échapper une chaîne ne peut tout simplement pas vous donner le même niveau d'assurance.

Il convient de noter que `appeler Get User With Name ('$ name');` avec `$ name` obtenu à partir d'une entrée utilisateur est toujours risqué.Et si `$ name =" jmoreno '); drop database; - "`?
Ian Ringrose
2020-04-22 17:43:29 UTC
view on stackexchange narkive permalink

Je peux avoir une politique pour toujours utiliser des procédures stockées et / ou des instructions préparées avec n'importe quelle base de données pour laquelle j'écris un logiciel un jour donné. Mon code c # (par exemple) a alors le même aspect quelle que soit la base de données choisie par mon employeur actuel, il est donc facile de le repérer lorsque je n'utilise pas d'instructions préparées, etc.

Les instructions préparées ne sont pas importantes, ce qui importe jamais en utilisant des opérateurs de chaîne pour créer le SQL à envoyer à la base de données.

mysql_real_escape_string () est un cas spatial qui n'est l'option que pour une base de données, donc comment apprendre quelque chose qui peut ne pas être utile pour la prochaine base de données avec laquelle je dois coder?

Damon
2020-04-23 00:13:46 UTC
view on stackexchange narkive permalink

Les procédures stockées sont supérieures non seulement parce qu'elles constituent une défense efficace contre certaines attaques, y compris l'injection. Ils sont supérieurs parce que vous obtenez plus en faisant moins, et de manière plus sécurisée, avec une «preuve» de sécurité de facto. Alors que le simple échappement des chaînes est loin de fournir cette "preuve".

Comment cela?

Une chaîne de requête, même si les données sont correctement échappées, est un morceau de texte. Le texte est odieux par nature. Le texte est analysé, ce qui prend du temps et peut mal tourner de plusieurs manières, puis le moteur de base de données fait quelque chose . Qu'est ce que ça fait? Vous ne pouvez jamais être sûr à 100%.

Vous pourriez oublier d'appeler la fonction d'échappement de chaîne, ou la fonction d'échappement de chaîne pourrait être défectueuse d'une manière qui pourrait être exploitée. Peu probable, mais même sur une requête correctement échappée à 100%, il est en principe possible de faire quelque chose de différent. Oh bien sûr, il y a toujours un contrôle d'accès et autre pour limiter les dommages possibles, mais peu importe. Il n'en reste pas moins qu'en principe, vous lancez une chaîne au moteur de base de données qui n'est pas vraiment très différente de l'envoi de code exécutable, puis vous vous attendez à ce qu'il fasse quelque chose , ce qui, espérons-le, est exactement ce que vous voulez .

Les procédures stockées, par contre, encapsulent exactement une opération spécifiée, jamais rien de différent. Envoyez ce que vous voulez, l'opération réelle qui se produira est déjà définie.
Les procédures stockées sont, en principe, analysées et optimisées exactement une fois, et (éventuellement, pas nécessairement, mais du moins en théorie) compilées en une représentation particulièrement rapide (par exemple une forme de bytecode).

Alors ... vous avez oublié d'échapper une chaîne? On s'en fout. La fonction d'échappement de chaîne ne fonctionne pas correctement? On s'en fout. La procédure stockée ne peut jamais faire quoi que ce soit que vous ne lui avez pas demandé de faire à un moment antérieur. La pire chose à arriver est que quelqu'un essayant d'exploiter le serveur parvient à insérer des déchets comme son nom d'utilisateur ou autre. Qui s'en soucie.

Ainsi, vous bénéficiez d'une bien meilleure sécurité et le serveur doit également effectuer moins de travail (c'est-à-dire que les requêtes s'exécutent plus rapidement). Vous gagnez des deux côtés (ce qui est rare car vous avez généralement un compromis).

De plus, d'un point de vue purement "esthétique", pas que cela compte dans la pratique, les choses sont la façon dont ils devraient être . La base de données ne reçoit que des données et exécute une sorte de programme pour ce compte, à sa seule discrétion.

Konchog
2020-04-22 14:51:13 UTC
view on stackexchange narkive permalink

Au niveau stratégique, le problème est lié à la vigilance: lorsque nous écrivons du code, si nous devons faire quelque chose de plus pour garantir la prévention d'un problème de sécurité (ou de sûreté, ou toute autre forme de qualité / performance), alors nous devons être vigilants pour le faire.

C'est, je crois, le principal problème lié à l'utilisation d'une fonction «d'échappement».

Ce qui aggrave le problème, c'est que, parce que le La fonction 'escape' est exécutée en dehors de la construction / évaluation de la requête elle-même, il n'y a pas de moyen simple ou efficace de pouvoir auditer toutes les requêtes concernant la présence ou l'absence d'évasion.

Pour éviter cette faiblesse, il faut transformer la composition escape / sql en une fonction - qui est essentiellement ce qu'est une instruction préparée, ou utiliser une couche abstraite pour son sql (par exemple, une sorte de ORM).

En tant que singe SQL, aucune des deux options n'est merveilleuse. Surtout lorsqu'il s'agit de structures SQL complexes (par exemple, des tables de clés primaires à 3 champs avec plusieurs jointures à gauche, y compris en utilisant la même table deux fois, avec un alias: pas inhabituel pour les structures arborescentes).

Je ne parle pas théoriquement: c'est une expérience pratique. Nous avons commencé par utiliser des mécanismes d'échappement, puis nous nous sommes fait prendre - heureusement par un stylo. agence de test - qui a trouvé une évasion manquante (le cas en question était la valeur d'un cookie de session qui n'avait pas été échappé). Ils l'ont démontré en injectant "select sleep (10);" - une manière brillante de tester / démontrer les injections.

(En allant un peu hors sujet, il est presque impossible pour l'équipe de développement d'écrire des tests d'injection pour leur propre code. Nous avons tendance à voir les choses uniquement à partir de une position. C'est pourquoi l'entreprise recommande toujours des agences de test de stylo tierces et totalement indépendantes.)

Alors, oui. escape () en tant que système autonome est un moyen très faible d'assurer la protection contre les injections. Vous voulez toujours intégrer la protection dans le cadre de la construction de la requête, car il est important de ne pas dépendre de la vigilance - mais plutôt d'être forcé -par défaut- pour vous assurer que les attaques par injection SQL sont prises en compte.

Dharman
2020-04-22 21:02:33 UTC
view on stackexchange narkive permalink

Vous devez comprendre que mysql_real_escape_string () n'est pas une protection contre l'injection SQL. Il s'agit simplement d'un piratage destiné à réduire les dommages et à limiter les vecteurs d'attaque potentiels. Rien dans le nom ou dans la documentation officielle de mysql_real_escape_string () n'indique que cette fonction doit être utilisée pour empêcher l'injection SQL.

L'injection SQL se produit lorsque vous autorisez les données variables à faire partie de votre chaîne SQL. Lors de la création de SQL avec des données dynamiques, il est difficile de garantir que le SQL ne sera pas interrompu. Une entrée non autorisée pourrait interrompre le SQL et endommager vos données ou divulguer les informations.

SQL doit être constant, tout comme le reste de votre code. Autoriser la saisie de variables dans SQL est vulnérable à des attaques similaires à celles de eval () avec une entrée de variable. Vous ne pouvez jamais être sûr de ce qui est exécuté.

Pour éviter cela, vous devez vous assurer que le SQL est constant et ne change pas avec l'entrée. La solution à cela sont les espaces réservés. Vous avez paramétré les données et utilisez des espaces réservés aux endroits où les littéraux iront. Aucune fuite n'est nécessaire. Ensuite, vous préparez une telle déclaration et transmettez les données séparément pendant l'exécution. Le SQL est toujours le même et les données n'ont aucun moyen d'affecter le SQL et de modifier son comportement.

Les procédures stockées ne sont pas un moyen sûr d'empêcher les injections SQL. Similaire à échapper, il ne limite que les vecteurs d'attaque.



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