web-dev-qa-db-fra.com

Assainissement de l'entrée pour les requêtes paramétrées

Si j'utilise partout des requêtes entièrement paramétrées, est-il toujours nécessaire et/ou pertinent pour la sécurité de nettoyer en quelque sorte les entrées? Par exemple. vérifier que les adresses e-mail sont valides avant d'envoyer une requête paramétrée sur la base de données ou de filtrer certains caractères spéciaux du texte?

Je pense à des outils tiers bénins, mais pas si bien conçus (peut-être des scripts auto-écrits par l'administrateur, ou des CrystalReports sophistiqués faits par un non-technicien) essayant de consommer des données non stérilisées de notre base de données.

En ce moment, nous avons un support complet Unicode contre SQL Server (MySQL semble avoir des problèmes avec Emojis), je ne sais pas comment filtrer les risques de sécurité sans perdre cette propriété.

16
Alexander

Non, ce n'est pas nécéssaire. Mais s'il vous plaît, lisez la suite.

Input sanitization est un terme horrible qui prétend que vous pouvez agiter une baguette magique sur les données et en faire des "données sûres". Le problème est que la définition de "sûr" change lorsque les données sont interprétées par différents logiciels.

Les données qui peuvent être incorporées dans une requête SQL peuvent ne pas être sécurisées pour être incorporées dans HTML. Ou JSON. Ou des commandes Shell. Ou CSV. Et supprimer (ou rejeter purement et simplement) des valeurs afin qu'elles soient sûres pour être incorporées dans tous ces contextes (et dans bien d'autres) est trop restrictif.

Alors, que devrions-nous faire? Assurez-vous que les données ne sont jamais en mesure de nuire.

La meilleure façon d'y parvenir est d'éviter en premier lieu l'interprétation des données. Les requêtes SQL paramétrées en sont un excellent exemple; les paramètres ne sont jamais interprétés comme SQL, ils sont simplement mis dans la base de données ainsi que les données.

Pour de nombreuses autres situations, les données doivent encore être incorporées dans d'autres formats, par exemple HTML. Dans ce cas, les données doivent être échappées pour cette langue particulière au moment où elles sont intégrées. Ainsi, pour empêcher XSS, les données sont échappées HTML au moment de la visualisation. Pas au moment de l'entrée. La même chose s'applique à d'autres situations d'intégration.

Alors, devrions-nous simplement transmettre tout ce que nous obtenons directement à la base de données?

Peut être. Ça dépend.

Il y a certainement des choses que vous pouvez vérifier sur les entrées utilisateur, mais cela dépend fortement du contexte. Parce que la désinfection est mal définie et mal utilisée, je préfère appeler cela validation.

  • Par exemple, si un champ est censé être un entier, vous pouvez certainement valider ce champ pour vous assurer qu'il contient un entier (ou peut-être NULL).
  • Vous pouvez certainement effectuer une validation sur les champs de courrier électronique (bien que certaines personnes soutiennent qu'il n'y a pas grand-chose que vous puissiez faire à part vérifier la présence d'un @, et ils ont un bon point).
  • Vous pouvez exiger que les commentaires aient une longueur minimale et maximale.
  • Vous devriez probablement vérifier que toute chaîne ne contient que des caractères valides pour son codage (par exemple, aucune séquence UTF-8 non valide).
  • Vous pouvez restreindre un nom d'utilisateur à certains caractères, si cela convient à votre base d'utilisateurs.
  • Une longueur minimale pour les mots de passe est, bien sûr, incroyablement courante.

Comme vous pouvez le voir, ces vérifications sont très dépendantes du contexte. Et tous doivent aider à augmenter les chances que vous vous retrouviez avec des données qui ont du sens. Ils ne sont pas destinés à protéger votre application contre les entrées malveillantes (injection SQL, XSS, injection de commande, etc.), car ce n'est pas le lieu de le faire.

Les utilisateurs doivent être libres de taper '; DROP TABLE users; -- sans que leur poste soit rejeté ou modifié vers \'; DROP TABLE users; --. Notez que je peux inclure un tel contenu "malveillant" sur sec.SE!

Donc, pour répondre à votre question d'origine:

... est-il toujours nécessaire et/ou pertinent pour la sécurité de nettoyer en quelque sorte les entrées?

Non, ça ne l'est pas. Mais veuillez échapper correctement les données si nécessaire avant de les générer. Et pensez aux validations, le cas échéant.

Je pense à des outils tiers bénins, mais pas si bien conçus (peut-être des scripts auto-écrits par l'administrateur, ou des CrystalReports sophistiqués faits par un non-technicien) essayant de consommer des données non stérilisées de notre base de données.

Ensuite, échappez ou filtrez les données avant de les exporter vers ces outils, mais ne modifiez pas les données de votre base de données.

Mais vraiment, ces scripts devraient être corrigés ou réécrits en gardant à l'esprit la sécurité.

(MySQL semble avoir des problèmes avec Emojis)

Peu hors sujet, mais jetez un œil au utfmb4 charset pour MySQL;)

17
marcelm

Si j'utilise partout des requêtes entièrement paramétrées, est-il toujours nécessaire et/ou pertinent pour la sécurité de nettoyer en quelque sorte les entrées?

Oui. C'est toujours une bonne idée de nettoyer l'entrée avant de l'envoyer à la base de données.

Les requêtes paramétrées peuvent vous sauver des attaques par injection SQL, mais peuvent ne pas s'avérer bénéfiques en cas d'attaques XSS stockées. Si un utilisateur envoie un code javascript malveillant dans votre formulaire, que vous le stockez correctement dans votre base de données et que vous affichez le même champ ailleurs, le script malveillant peut s'exécuter sur le navigateur de la victime.

C'est toujours une bonne idée de désinfecter l'entrée avant de l'envoyer à l'avance et de désinfecter la sortie avant de l'envoyer au navigateur du client.

EDIT: Comme indiqué dans les commentaires, la désinfection est différente des valeurs de codage/d'échappement. La désinfection signifie ici que les entrées peuvent être validées pour certains contrôles de base avant de les transmettre à la base de données (ou à toute autre couche). Par exemple, un champ qui attend une adresse e-mail peut être validé pour une adresse e-mail valide, un champ pour l'âge ne peut être validé que pour un entier, etc. Les expressions régulières s'avèrent être d'une immense aide ici. Il convient de noter que ces contrôles doivent être placés sur le front-end (côté client) ainsi que sur le back-end.

Dans le cas de champs qui attendent du texte enrichi, vous pouvez implémenter Politique de sécurité du conten sur les pages où l'entrée utilisateur sera affichée. Vous pouvez également utiliser un assainisseur HTML pour assainir l'entrée utilisateur.

8
pri

Oui, vous devez toujours nettoyer les données d'entrée. L'assainissement ne consiste pas seulement à vous protéger des injections, mais aussi à valider les types, les valeurs restreintes (énumérations), les plages, etc. Bien qu'un attaquant puisse ne pas être en mesure de manipuler votre SQL, ils peuvent toujours provoquer un comportement indésirable dans le reste de ton application.

Par exemple, si un attaquant modifiait une valeur d'énumération, pourrait-il manipuler le système? Ont-ils juste changé de rôle, de type d'utilisateur, etc ...? Alternativement, ils pourraient entrer une valeur supérieure à celle qui peut être acceptée dans votre schéma ou le type de données (octet v int32, int64), cela pourrait entraîner le blocage de l'application qui expose des informations ou laisse des données orphelines modifiées (non traitées).

3
JonnySchnittger