web-dev-qa-db-fra.com

Le filtrage des guillemets simples est-il absurde?

Les testeurs de pénétration ont découvert que nous autorisons les guillemets simples dans les champs de données soumis et veulent que nous appliquions des règles (validation des entrées) pour ne les autoriser dans aucune valeur.

Bien que je sache que les guillemets simples sont populaires pour les attaques par injection SQL, je suis fortement en désaccord avec le fait qu'ils ne devraient pas être autorisés comme entrée valide. Je préconise d'empêcher réellement l'injection SQL en utilisant des instructions préparées (qui citent correctement les valeurs) au lieu de filtrer tout ce qui ressemble à distance à un fragment SQL.

Mon cas:

  • Les noms de personnes peuvent contenir des guillemets simples (tels que O'Reilly )
  • Les champs de texte peuvent contenir des guillemets simples (tels que Je suis presque sûr )
  • Les champs numériques peuvent contenir des guillemets simples ( EUR 1'000'000 )
  • et beaucoup plus

J'ai vu d'autres cas où l'application de règles de prévention des injections SQL a enregistré des données valides pour les raisons les plus idiotes (nom " Andreas " rejeté car il contient un [~ # ~] et [~ # ~] , et divers mots courants dans les champs de texte brut ont été rejetés car ils contenaient les mots clés " sélectionnez "," insérez "," mettez à jour "ou" supprimer ").

Quelle est la position des professionnels de la sécurité à ce sujet?

Devons-nous rejeter la mise en œuvre de la validation des entrées pour les guillemets simples pour les raisons que j'ai indiquées?

237
Peter Walser

Vous devez implémenter la validation des entrées comme méthode de défense en profondeur. La validation des entrées ne doit donc pas être votre principale défense contre l'injection SQL, il convient de préparer des instructions. Comme défense supplémentaire, vous devez restreindre les entrées autorisées.

Cela ne devrait jamais restreindre la fonctionnalité. S'il existe un cas d'utilisation légitime pour avoir des apostrophes en entrée, vous devez l'autoriser. Vous devez donc autoriser les guillemets simples dans les champs de nom, les descriptions, les mots de passe, mais pas dans les champs de nombre, les champs de nom d'utilisateur, les champs de plaque d'immatriculation.

Bloquer les guillemets simples dans toutes les entrées est une folie. Cela rompt la fonctionnalité de l'application et n'est même pas la bonne solution contre l'injection SQL.

Considérez la possibilité que vous ayez mal compris l'entreprise pentestante. Si c'est sérieusement leur conseil, cela reflète mal la société de pentesting et je vous conseille de rechercher un partenaire de pentesting qui aide à sécuriser correctement votre logiciel, au lieu de le rendre inutilisable.

321
Sjoerd

C'est clairement faux dans le contexte des attaques par injection - votre couche de base de données traite correctement les chaînes ou non. Étant donné que les apostrophes sont valides dans les noms et le texte libre, leur blocage complet interrompra l'application et leur blocage sélectif ne résoudrait pas les problèmes d'injection.

Mais la validation stricte des entrées est une bonne pratique sur les principes généraux, et être trop permissif n'a pas de sens dans les cas où l'apostrophe ne fait pas partie d'une valeur légitime. Vous donnez l'exemple de EUR 1'000'000, qui est un format spécifique aux paramètres régionaux (Suisse uniquement, AFAIK) - mais autoriser le format à faire partie de la valeur n'a aucun sens. Si l'utilisateur entre 1,500, votre application doit-elle les stocker telles quelles? Devrez-vous décider chaque fois qu'il est traité s'il doit être interprété comme 1.5 ou comme 1500? Il serait plus logique de gérer la présentation spécifique aux paramètres régionaux côté client et de traiter la valeur numérique sous une forme canonique en interne.

Donc, la réponse ici dépendrait de la question de savoir si l'audit se plaint de domaines spécifiques où cela a du sens ou s'il recommande une interdiction générale des apostrophes. Si le premier, c'est un point légitime. Si ce dernier est stupide, il suit probablement aveuglément une liste de contrôle.

27
Christoph Burschka

Étape 1) Paramétrez votre SQL.

Étape 2) Assurez-vous que vous utilisez la bibliothèque de connexion SQL DB pour définir les valeurs de vos paramètres, pas simplement en les définissant en ligne. Il s'agit de la véritable défense contre l'injection SQL.

Étape 3) Ne faites pas de construction de requêtes en SQL. De cette façon réside la folie.

Étape 4) ajoutez un commutateur de configuration pour propager l'erreur jusqu'à l'utilisateur. Allumez-le pendant le test.

Étape 5) Dites à vos testeurs de pénétration de trouver un moyen de générer une erreur SQL avec un nombre impair de guillemets simples ou de la fermer.

17
Joshua

Les instructions préparées (requêtes paramétrées) sont excellentes, assurez-vous simplement de les implémenter correctement. J'ai vu des implémentations de "déclaration préparée" qui étaient tout aussi vulnérables. Pour une discussion sur les détails d'implémentation, je recommande le débordement de pile.

Aussi rien de mal à la défense en profondeur (validation des entrées dans ce cas) mais faites-le bien ... rejeter tous les guillemets simples n'est probablement pas la meilleure pratique :)

12
DarkMatter

Je ne suis pas un agent de sécurité. Je suis un programmeur qui doit maintenir un code sécurisé. C'est ce que j'appelle une pratique "fragile". Les points d'entrée sont dispersés sur un projet typique. Les trouver et les désinfecter tous demandent beaucoup de travail pour résoudre un seul problème, beaucoup de maintenance minutieuse et des tracas pour s'assurer qu'il reste efficace à mesure que le code change, et plein d'hypothèses qui le rendent inefficace.

Utilisez plutôt des pratiques plus faciles à maintenir, en couches, contextuelles et qui résolvent une large gamme de problèmes. Vous n'avez alors pas besoin d'un filtrage trop large et coûteux.

Vous ne pouvez pas sécuriser les entrées si vous ne savez pas comment elles seront utilisées.

Supposons que vous avez "sécurisé" votre système en supprimant toutes les citations simples de toutes les entrées à travers le conseil d'administration. Très bien, vous êtes sûr contre un type d'attaque par injection SQL. Et si cette entrée est utilisée dans un ...

  • Requête MySQL qui permet des guillemets doubles
  • Fonctionnement du système de fichiers
  • Commande shell
  • Requête réseau
  • Nom de la méthode
  • Nom du cours
  • eval

Chacun d'eux a différents caractères spéciaux, séquences d'échappement, règles de citation et pratiques de sécurité. Vous ne pouvez pas prévoir comment votre entrée sera utilisée lorsqu'elle entrera en jeu. Essayer de supprimer tous les caractères spéciaux est une folie et ne "résout" qu'une seule classe d'attaque.

Ou que faire si l'utilisateur est autorisé à saisir une limite de pages. Cette limite est utilisée à bon escient dans une requête paramétrée; pas d'injection SQL, yay! L'utilisateur entre 9999999999 et maintenant vous êtes ouvert à une attaque DOS.

Vous devez appliquer les mesures de sécurité appropriées au point où l'opération potentiellement non sécurisée est effectuée. Cela prend en compte de nombreux facteurs propres à l'opération; la désinfection des caractères saisis n'en est qu'un.

Et tant que vous le faites, vous pouvez aussi bien paramétrer vos requêtes. Ensuite, il n'est plus nécessaire de faire tout le travail et les dommages des devis de suppression de couverture.

Le filtrage de toutes les entrées est difficile.

Il existe de très nombreuses façons d'obtenir et de transmettre des informations dans un projet donné:

  • entrées de formulaire
  • urls
  • noms de fichiers
  • contenu du fichier
  • requêtes de base de données
  • lectures réseau
  • variables d'environnement

Ce sont généralement des formes assez libres et peuvent utiliser de nombreuses bibliothèques différentes. Je ne connais aucun outil d'analyse statique qui vérifie que toutes les entrées potentiellement vulnérables ont subi un filtrage. Certaines langues ont un système taint , mais elles sont difficiles à utiliser efficacement. Même si vous filtrez toutes les entrées, sans outil d'analyse statique, les entrées non filtrées seront réintroduites au fur et à mesure du développement. Cela demande beaucoup d'efforts pour un résultat incomplet et coûteux à maintenir, ce qui entrave la fonctionnalité.

En revanche, il n'y a généralement qu'une seule façon d'exécuter SQL dans un projet. Des outils statiques et d'exécution existent pour détecter automatiquement une éventuelle injection SQL. Vous pouvez même interdire complètement les chaînes et exiger que toutes les requêtes soient des objets de requête SQL. Ces bonnes pratiques sont faciles à maintenir et de plus en plus intégrées dans les outils et les bibliothèques SQL.

Les "pare-feu" conduisent à une sécurité laxiste.

Semblable à la façon dont certains réseaux de bureaux ont des pratiques très peu sûres parce que "nous avons un pare-feu", il y a un risque que l'équipe devienne paresseuse à propos de la sécurisation de son code parce que "l'entrée est sûre". L'entrée n'est certainement pas sûre.

Coût d'opportunité

Certains pourraient dire "pourquoi pas les deux?" Vous n'avez que quelques heures pour travailler sur un projet. Une pratique à faible efficacité et à maintenance élevée est une tâche ardue. Sa mise en œuvre et sa maintenance vous feront perdre un temps limité à des pratiques plus efficaces et plus faciles à entretenir. Dans le pire des cas, vous passerez tellement de temps à jouer avec des entrées et les problèmes ultérieurs causés par le filtrage trop agressif, que vous n'aurez jamais le temps de prendre les mesures de sécurité appropriées.

En bref, le filtrage des entrées coûte cher, fuit, difficile à entretenir, ne peut pas résoudre le problème et pourrait l'aggraver.

11
Schwern

Comme vous l'avez dit vous-même, si vous utilisez des requêtes paramétrées, les guillemets simples ne sont pas un problème. Dans ce cas, vous pouvez rejeter leurs conseils. Dans ce cas, mettez en évidence le fait que vous êtes en utilisant des requêtes paramétrées et que cela facilite également la convivialité (en utilisant vos exemples précédents).

8
Philip Rowlands

Si vous êtes sûr à 100% que vous empêchez toujours l'injection SQL partout, cela n'a aucun sens.

Cependant, l'injection SQL est l'un des risques de sécurité les plus courants, et même si vous êtes sûr d'avoir correctement écrit votre application pour utiliser des paramètres, un DBA bâclé peut exécuter une requête à risque pour SQL de second ordre injection . Il pourrait même ne pas être stocké n'importe où, il pourrait simplement s'agir d'une requête pour copier une table.

Les attaques de second ordre sont plus difficiles à exécuter, mais plus difficiles à protéger. La protection contre les attaques de second ordre signifie que chaque instruction SQL dynamique exécutée sur la base de données avec des autorisations d'écriture doit être vérifiée pour un risque d'injection SQL, pas seulement les instructions SQL qui traitent les entrées provenant de sources non fiables.

Refuser les devis partout est une protection bâclée contre les attaques de second ordre, mais les rend moins probables. Dans un monde idéal, cela ne serait pas nécessaire, mais malheureusement nous ne vivons pas dans un seul.

Si de nombreux utilisateurs ont une forme quelconque d'accès en écriture sur la base de données et sont capables d'écrire leurs propres instructions SQL, cela peut être une mesure de sécurité raisonnable. Si votre application est le seul moyen d'accéder à la base de données et que seuls les utilisateurs très compétents peuvent exécuter leurs propres requêtes avec un accès en écriture, cela n'est généralement pas nécessaire.

8
Erik A

Bien que je ne connaisse pas les détails de votre demande, je suis votre argument.

Il existe des champs qui n'ont pas besoin de contenir certains caractères. Avec ces champs, vous pourriez utiliser la validation d'entrée pour filtrer les guillemets simples (et les guillemets doubles, etc.).

Si votre échappement ne fonctionne pas correctement, la validation des entrées peut être une stratégie d'atténuation, mais l'utilisation d'instructions préparées (correctement) devrait être l'approche préférable pour atténuer les risques d'injection SQL.

6
Tobi Nary

Si c'est le résultat d'un véritable test de pénétration, ils devraient être en mesure de vous fournir une valeur à soumettre qui prouve qu'il s'agit d'un problème exploitable. S'ils ne peuvent pas, je suggère de demander un test de pénétration approprié, où ils prouvent que cela est exploitable.

Si toutefois cela est le résultat d'une analyse de vulnérabilité générique, je m'attendrais à des réponses génériques floues comme celle-ci, qui indiqueraient simplement la possibilité d'insérer une citation unique. Dans ce cas, si vous êtes satisfait de l'absence de problème, vous pouvez ignorer ce résultat avec plaisir.

4
Jason Leaman

Je pense que c'est une question de perspective. Votre système a une exigence fonctionnelle qui doit venir en premier. Cela ne signifie pas que cela ne vaut pas la peine d'examiner la question de la validation des entrées. BTW, les deux ne sont pas directement en désaccord. Je ne le recommande pas, mais il serait possible de coder et de décoder dans le frontal et de faire en sorte que le stockage et la requête SQL utilisent le formulaire codé.

L'équilibre est subjectif et dépend d'une multitude de choses non mentionnées. Vous pourriez essayer de leur demander de clarifier. Ils peuvent avoir une très bonne raison, non.

1
ANone

D'un ancien développeur Web et maintenant un testeur de stylo moi-même, je ne voudrais pas restreindre l'entrée des utilisateurs, mais cela peut être un problème majeur. Je sais que j'ai moi-même utilisé cette technique pour compromettre les applications Web et les bases de données.

Mon avis serait de vérifier l'installation de votre base de données et votre configuration de langue Web (php) pour gérer les caractères d'échappement, puis de coder un ou plusieurs modules pour itérer l'entrée afin de vous assurer qu'elle est correctement formatée.

Une apostrophe peut être une entrée valide, mais peut également échapper à votre instruction de base de données et introduire un vecteur d'attaque. Les bases de données et les langages Web ont des modules qui peuvent gérer ces types d'instances, mais c'est toujours une bonne idée d'écrire votre propre module à revérifier.

1
MrNiceGuy