La dépendance aux requêtes paramétrées est-elle le seul moyen de se protéger contre l'injection SQL?

13

Tout ce que j'ai vu sur les attaques par injection SQL semble suggérer que les requêtes paramétrées, en particulier celles dans les procédures stockées, sont le seul moyen de se protéger contre de telles attaques. Pendant que je travaillais (à l'époque des ténèbres), les procédures stockées étaient considérées comme une mauvaise pratique, principalement parce qu'elles étaient considérées comme moins maintenables; moins testable; fortement couplé; et verrouillé un système dans un seul fournisseur; ( cette question couvre d'autres raisons).

Bien que lorsque je travaillais, les projets ignoraient pratiquement la possibilité de telles attaques; diverses règles ont été adoptées pour sécuriser la base de données contre toute forme de corruption. Ces règles peuvent être résumées comme suit:

  1. Aucun client / application n'avait un accès direct aux tables de la base de données.
  2. Tous les accès à toutes les tables se faisaient via des vues (et toutes les mises à jour des tables de base ont été effectuées via des déclencheurs).
  3. Tous les éléments de données avaient un domaine spécifié.
  4. Aucun élément de données ne pouvait être annulé - cela avait des implications qui obligeaient parfois les DBA à grincer des dents; mais a été appliquée.
  5. Les rôles et les autorisations ont été configurés de manière appropriée - par exemple, un rôle restreint pour donner uniquement aux vues le droit de modifier les données.

Un ensemble de règles (appliquées) comme celui-ci (mais pas nécessairement cet ensemble particulier) est-il donc une alternative appropriée aux requêtes paramétrées pour empêcher les attaques par injection SQL? Sinon, pourquoi pas? Une base de données peut-elle être sécurisée contre de telles attaques par des mesures spécifiques à la base de données (uniquement)?

ÉDITER

L'accent mis sur la question a légèrement changé, à la lumière des premières réponses reçues. Question de base inchangée.

EDIT2

L'approche consistant à s'appuyer sur des requêtes paramétrisées ne semble être qu'une étape périphérique de la défense contre les attaques de systèmes. Il me semble que des défenses plus fondamentales sont à la fois souhaitables et peuvent rendre la dépendance à de telles requêtes inutile, ou moins critique, même pour se défendre spécifiquement contre les attaques par injection.

L'approche implicite dans ma question était basée sur le "blindage" de la base de données et je ne savais pas si c'était une option viable. Des recherches supplémentaires ont suggéré qu'il existe de telles approches. J'ai trouvé les sources suivantes qui fournissent quelques indications sur ce type d'approche:

http://database-programmer.blogspot.com

http://thehelsinkideclaration.blogspot.com

Les principales caractéristiques que j'ai tirées de ces sources sont:

  1. Un vaste dictionnaire de données, combiné avec un vaste dictionnaire de données de sécurité
  2. Génération de déclencheurs, requêtes et contraintes à partir du dictionnaire de données
  3. Minimisez le code et maximisez les données

Bien que les réponses que j'ai reçues jusqu'à présent soient très utiles et mettent en évidence les difficultés résultant du non-respect des requêtes paramétrées, elles ne répondent finalement pas à ma ou mes questions d'origine (désormais soulignées en gras).

Chris Walton
la source
Je n'achète pas les arguments contre les procédures stockées. Ils ne sont tout simplement pas vrais.
Konrad Rudolph
Qu'en est-il de l'exigence no-nulls?
Mark Canlas
2
@Konrad Rudolph - Si vous écrivez votre application sur MySQL et décidez ensuite de migrer vers DB2, pensez-vous vraiment que les procédures stockées vont être compatibles? De même si vous souhaitez migrer vers SQLLite? Supposons également que vous mettez à niveau votre système d'exploitation - si vos procédures stockées sont compilées en C (ce qu'elles sont dans DB2), elles auront probablement toutes besoin d'être recompilées. Ce sont des arguments raisonnables - pas absolus, mais raisonnables.
Matthew Flynn
@Matthew Duh. Je pensais en fait à des «requêtes paramétrées» en lisant cela et en commentant. Procédure stockée = toute autre histoire.
Konrad Rudolph

Réponses:

25

Les proc stockés ne protègent pas automatiquement contre l'injection. Et ça

CREATE PROC proc
  @id VARCHAR(5)
AS
BEGIN
  EXEC("SELECT * FROM Client WHERE ClientId = " + @id);
END

L'utilisation de requêtes paramétrées vous protégera contre l'injection, qu'elles soient en procs ou non.

Craig
la source
Merci de l'accent mis sur les requêtes paramétrées plutôt que sur les procs. Cependant, je demande si la base de données peut être protégée par des méthodes autres que de telles requêtes - en particulier des méthodes qui sont limitées à la couche de base de données uniquement.
Chris Walton
1
+1 En plus de cela, je voudrais déclarer que les proc stockés sont généralement considérés comme sécurisés car c'est le seul moyen d'empêcher les utilisateurs d'accéder directement aux tables tout en conservant un moyen de récupérer les données. C'est le seul moyen de garantir des privilèges basés sur des lignes et des colonnes lorsque l'utilisateur doit avoir un accès direct à la base de données avec son client sans rien entre les deux.
Falcon
2
@Chris - Je pense que ce que Craig dit ici, c'est que vous ne pouvez pas supposer que les procs vous protègent réellement. Ce n'est peut-être pas une réponse complète, plutôt une correction de l'hypothèse du titre.
Jon Hopkins
@Jon - J'ai modifié le titre de la question et apporté quelques modifications à la question, à la lumière de la correction de Craig. Je n'étais pas au courant de l'hypothèse que je faisais dans la question, jusqu'à ce que j'ai commencé à recevoir des réponses.
Chris Walton
2
Pour renforcer ce que Craig écrit ci-dessus, voir databasesecurity.com/dbsec/lateral-sql-injection.pdf , "Lateral SQL Injection: A New Class of Vulnerability in Oracle"
Bruce Ediger
11

Un ensemble de règles (appliquées) comme celui-ci constitue-t-il donc une alternative appropriée aux procédures stockées pour prévenir les attaques par injection SQL? Sinon, pourquoi pas?

Non, car ils infligent une pénalité assez lourde aux développeurs. Une ventilation par article:

1. Aucun client / application n'avait un accès direct aux tables de la base de données.

Utilisez des rôles. Les clients ne doivent pouvoir accéder à la base de données que par l'intermédiaire d'un rôle restreint qui ne dispose que des accès SELECT, INSERT, UPDATE et DELETE aux tables (et lignes, si possible) auxquelles il a besoin d'accéder. Si vous voulez vous assurer qu'aucun client ne peut spammer ou supprimer toutes les entrées, utilisez une API pour la modification des données.

2. Tous les accès à toutes les tables se faisaient par des vues.

Cela pourrait être quelque chose de négligeable à un coût de performance énorme, selon l'efficacité des vues. C'est une complexité inutile qui ralentit le développement. Utilisez des rôles.

3. Tous les éléments de données avaient un domaine spécifié.

Cela pourrait demander beaucoup de travail et devrait probablement être normalisé dans une table distincte.

4. Aucun élément de données ne pouvait être annulé - cela avait des implications qui obligeaient les DBA à grincer des dents à l'occasion; mais a été appliquée.

C'est tout simplement faux. Si les développeurs ne sont pas en mesure de gérer NULLs, vous avez de gros problèmes.

Une base de données peut-elle être sécurisée contre de telles attaques par des mesures spécifiques à la base de données (uniquement)?

Vous n'avez pas besoin de procédures stockées, utilisez simplement des requêtes paramétrées avec une fonction qui échappe aux arguments, comme pg_query_params . Bien sûr, si votre base de données est accessible en écriture ou si le rôle client a un accès complet à tout, vous êtes quand même foutu. Quelqu'un doit juste venir et se rendre compte de ce que fait le client, puis préparer un client en cinq minutes qui détruit (ou pire, empoisonne) votre base de données.

l0b0
la source
1
Domaine: en.wikipedia.org/wiki/Data_domain
Dan McGrath
+1 pour les rôles. Ils sont un contributeur majeur à cela - je n'ai pas inclus de rôles dans ma question, mais ils faisaient partie de la configuration - en particulier, les vues se sont vu attribuer un rôle restreint comme vous le suggérez pour les clients. Point pris sur le coup de performance des vues. Les domaines comprenaient des tests de validation - plages et longueur principalement. Vos commentaires sur la règle annulable des données sont beaucoup plus polis que certains que j'ai entendu à propos de cette règle. Je n'ai pas déclaré explicitement que les autorisations seraient configurées correctement, bien que ce soit mon hypothèse.
Chris Walton
6

Je ne suis pas sûr que vos règles vous protègent complètement.

Le premier problème est que vous déclarez qu'elles sont appliquées, mais, en plus des frais généraux importants, je n'ai jamais vu d'application parfaite.

Deuxièmement, ma lecture est que des règles comme celles-ci pourraient rendre les choses plus difficiles à exploiter, mais elles ne l'empêchent pas. Par exemple, ne pas avoir d'accès direct aux tables ne change pas grand-chose si les vues vous permettent d'accéder aux mêmes données. Si le client doit faire quelque chose, une vue doit faciliter cela et si une vue le facilite, les mêmes fonctionnalités / données peuvent être utilisées par un attaquant.

N'oubliez pas non plus qu'il ne s'agit pas uniquement de mettre à jour ou de supprimer des données. Une partie de la vulnérabilité avec l'injection SQL est la collecte d'informations et pour cela vous ne vous souciez pas de savoir si les données ont été retransmises via la vue vCustomers ou la table Customers sous-jacente. Vous pouvez être protégé de certaines faiblesses mais pas de toutes. De même, si les mises à jour peuvent être effectuées par le client, même si elles sont effectuées via des déclencheurs, SQL peut être écrit pour déclencher les déclencheurs et effectuer des mises à jour.

(En ce qui concerne toutes les mises à jour effectuées via des déclencheurs, je vais dire deux choses: (1) lorsque je lis ceci, j'ai un peu mal à la bouche et (b) vous n'aimez pas les procédures stockées parce qu'elles ' re "moins maintenable; moins testable; hautement couplé; et verrouillé un système en un seul fournisseur" mais vous utilisez des déclencheurs sur lesquels les mêmes choses peuvent être dites.)

Tout ce dont vous avez besoin est d'un trou qui permet l'exécution d'instructions SQL (et je ne vois aucune de ces règles l'empêcher) et l'attaquant est là. Ils peuvent trouver une base de données très peu intuitive derrière eux, mais s'ils sont déterminés, cela les ralentir plutôt que de les arrêter).

L'autre chose ici est que vous ajoutez également de la complexité et (ainsi que la surcharge qui crée), la complexité a tendance à conduire à des trous qui peuvent être exploités.

Je ne dis pas qu'un tel ensemble de règles ne pourrait pas être créé - plus pourquoi vous dérangeriez? Ils semblent plus encombrants et moins fiables que de simplement suivre les méthodes largement acceptées de prévention de ce type d'attaque.

Jon Hopkins
la source
+1 pour avoir compris ma requête réelle à la lumière de mes hypothèses implicites et inconscientes, et pour y avoir répondu de manière appropriée. Quant à savoir pourquoi on pourrait s'embêter - je travaille sur un projet où une grande partie du code sera généré à partir d'une description pertinente de l'architecture - et une partie de cette architecture décrit comment générer des routines d'accès à la base de données. Il reste à déterminer la forme que prendront ces routines générées.
Chris Walton