108 votes

Prévention de l'injection SQL dans Node.js

Est-il possible d'empêcher les injections SQL dans Node.js (de préférence avec un module) de la même manière que PHP avait des instructions préparées qui les protégeaient.

Si oui, comment ? Si non, quels sont les exemples qui pourrait contourner le code que j'ai fourni (voir ci-dessous).


Un peu de contexte :

Je suis en train de créer une application web avec une pile back-end composée de Node.js + MySql en utilisant l'outil de gestion de l'application. node-mysql module. Du point de vue de la facilité d'utilisation, le module est excellent, mais il n'a pas encore implémenté quelque chose de similaire à la fonction de PHP Déclarations préparées (bien que je sois conscient que c'est sur le site de la Commission européenne). todo ).

D'après ce que j'ai compris, PHP met en œuvre des déclarations préparées, entre autres choses, a beaucoup aidé dans la prévention des injections SQL. Je crains cependant que mon application node.js ne soit ouverte à des attaques similaires, même avec l'échappement des chaînes fourni par défaut (comme dans l'extrait de code ci-dessous).

node-mysql semble être le connecteur mysql le plus populaire pour node.js, donc je me demandais ce que d'autres personnes pourraient faire (le cas échéant) pour tenir compte de ce problème - ou si c'est même un problème avec node.js pour commencer (je ne vois pas comment ce ne serait pas, puisque l'entrée côté utilisateur/client est impliquée).

Dois-je passer à node-mysql-native pour l'instant, puisqu'il fournit des déclarations préparées ? J'hésite à le faire, car il ne semble pas être aussi actif que node-mysql (bien que cela puisse simplement signifier qu'il est complet).

Voici un extrait du code d'enregistrement de l'utilisateur, qui utilise la balise désinfectant ainsi que la syntaxe de type déclaration préparée de node-mysql (qui, comme je l'ai mentionné plus haut, permet l'échappement des caractères), afin d'empêcher les scripts intersites et les injections sql, respectivement :

// Prevent xss
var clean_user = sanitizer.sanitize(username);

// assume password is hashed already
var post = {Username: clean_user, Password: hash};

// This just uses connection.escape() underneath
var query = connection.query('INSERT INTO users SET ?', post,
   function(err, results)
   {
       // Can a Sql injection happen here?
   });

65voto

Michael Pratt Points 781

En node-mysql effectue automatiquement l'échappement lorsqu'elle est utilisée comme vous le faites déjà. Voir https://github.com/felixge/node-mysql#escaping-query-values

17voto

hexacyanide Points 15723

La bibliothèque dispose d'un section dans le readme à propos de l'évasion. Il est natif de Javascript, donc je ne suggère pas de passer à node-mysql-native . La documentation indique ces directives pour l'échappement :

Edita: node-mysql-native est également une solution purement Javascript.

  • Les chiffres ne sont pas modifiés
  • Les booléens sont convertis en true / false chaînes de caractères
  • Les objets de type date sont convertis en YYYY-mm-dd HH:ii:ss cordes
  • Les tampons sont convertis en chaînes hexagonales, par exemple X'0fa5'
  • Les chaînes de caractères sont échappées en toute sécurité
  • Les tableaux sont transformés en liste, par exemple. ['a', 'b'] se transforme en 'a', 'b'
  • Les tableaux imbriqués sont transformés en listes groupées (pour les insertions en vrac), par ex. [['a', 'b'], ['c', 'd']] se transforme en ('a', 'b'), ('c', 'd')
  • Les objets sont transformés en key = 'val' paires. Les objets imbriqués sont convertis en chaînes de caractères.
  • undefined / null sont convertis en NULL
  • NaN / Infinity sont laissés tels quels. MySQL ne les prend pas en charge, et essayer de les insérer en tant que valeurs déclenchera des erreurs MySQL jusqu'à ce que le support soit implémenté.

Cela vous permet de faire des choses comme celles-ci :

var userId = 5;
var query = connection.query('SELECT * FROM users WHERE id = ?', [userId], function(err, results) {
  //query.sql returns SELECT * FROM users WHERE id = '5'
});

Ainsi que ceci :

var post  = {id: 1, title: 'Hello MySQL'};
var query = connection.query('INSERT INTO posts SET ?', post, function(err, result) {
  //query.sql returns INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL'
});

En plus de ces fonctions, vous pouvez également utiliser les fonctions d'échappement :

connection.escape(query);
mysql.escape(query);

Pour échapper aux identifiants des requêtes :

mysql.escapeId(identifier);

Et en réponse à votre commentaire sur les déclarations préparées :

Du point de vue de la convivialité, le module est excellent, mais il n'a pas encore implémenté quelque chose de semblable aux instructions préparées de PHP.

Les déclarations préparées sont sur le todo pour ce connecteur, mais ce module vous permet au moins de spécifier des formats personnalisés qui peuvent être très similaires aux déclarations préparées. Voici un exemple tiré du fichier readme :

connection.config.queryFormat = function (query, values) {
  if (!values) return query;
  return query.replace(/\:(\w+)/g, function (txt, key) {
    if (values.hasOwnProperty(key)) {
      return this.escape(values[key]);
    }
    return txt;
  }.bind(this));
};

Cela modifie le format de requête de la connexion afin que vous puissiez utiliser des requêtes comme celle-ci :

connection.query("UPDATE posts SET title = :title", { title: "Hello MySQL" });
//equivalent to
connection.query("UPDATE posts SET title = " + mysql.escape("Hello MySQL");

12voto

jas- Points 437

Pour vérifier si un module que vous utilisez est sécurisé ou non, vous pouvez emprunter plusieurs voies. Je vais aborder les avantages et les inconvénients de chacune d'entre elles afin que vous puissiez prendre une décision plus éclairée.

Actuellement, il n'y a pas de vulnérabilité pour le module que vous utilisez, mais cela peut souvent conduire à un faux sentiment de sécurité, car il pourrait très bien y avoir une vulnérabilité qui exploite le module/logiciel que vous utilisez et vous ne seriez pas alerté du problème jusqu'à ce que le fournisseur applique un correctif.

  1. Pour vous tenir au courant des vulnérabilités, vous devrez suivre les listes de diffusion, les forums, l'IRC et d'autres discussions liées au piratage. PRO : Vous pouvez souvent prendre connaissance de problèmes potentiels au sein d'une bibliothèque avant qu'un fournisseur n'ait été alerté ou n'ait publié un correctif pour remédier à l'avenue potentielle d'attaque sur son logiciel. CONTRE : Cette méthode peut prendre beaucoup de temps et nécessiter beaucoup de ressources. Si vous choisissez cette voie, un robot utilisant des flux RSS, l'analyse des journaux (journaux de discussion IRC) ou un système de gestion de l'information sur le Web peut être utile. Racloir L'utilisation de phrases clés (dans ce cas, node-mysql-native) et de notifications peut contribuer à réduire le temps passé à parcourir ces ressources.

  2. Créer un fuzzer, utiliser un fuzzer ou un autre cadre de vulnérabilité tel que metasploit , sqlMap etc. pour aider à détecter les problèmes que le vendeur n'a peut-être pas cherchés. PRO : Cela peut s'avérer être une méthode sûre pour garantir à un niveau acceptable si le module/logiciel que vous mettez en œuvre est sûr pour l'accès public. CONTRE : Cela peut également prendre du temps et coûter cher. L'autre problème provient des faux positifs ainsi que de l'examen non éclairé des résultats où un problème réside mais n'est pas remarqué.

La sécurité réelle, et la sécurité des applications en général, peut prendre beaucoup de temps et exiger beaucoup de ressources. Les responsables utiliseront toujours une formule pour déterminer la rentabilité (main-d'œuvre, ressources, temps, salaire, etc.) des deux options ci-dessus.

Quoi qu'il en soit, je me rends compte que ce n'est pas une réponse "oui" ou "non" que vous espériez, mais je ne pense pas que quiconque puisse vous donner cette réponse avant d'avoir effectué une analyse du logiciel en question.

5voto

Boy pro Points 272

Mysql-native a été dépassé, il est devenu MySQL2 qui est un nouveau module créé avec l'aide de l'équipe du module MySQL original. Ce module a plus de fonctionnalités et je pense qu'il a ce que vous voulez car il a des instructions préparées (en utilisant .execute()) comme en PHP pour plus de sécurité.

Il est également très actif (le dernier changement a été de 2-1 jours) Je ne l'ai pas essayé avant mais je pense que c'est ce que vous voulez et plus.

0voto

Khabir Points 151

Prévention des injections SQL

Injections SQL est une technique de piratage web courante pour détruire ou utiliser abusivement votre base de données. Pour éviter les injections SQL, vous devez utiliser l'échappement des valeurs lorsque les valeurs de la requête sont des variables fournies par l'utilisateur.

Échappez les valeurs des requêtes en utilisant la méthode mysql.escape() :

var adr = 'Mountain 21';
var sql = 'SELECT * FROM customers WHERE address = ' + mysql.escape(adr);
con.query(sql, function (err, result) {
  if (err) throw err;
  console.log(result);
});

Échappez les valeurs de la requête en utilisant la méthode placeholder ?

var adr = 'Mountain 21';
var sql = 'SELECT * FROM customers WHERE address = ?';
con.query(sql, [adr], function (err, result) {
  if (err) throw err;
  console.log(result);
});

Plus de détails

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X