it-roy-ru.com

Предотвращение внедрения SQL в Node.js

Можно ли предотвратить SQL-инъекции в Node.js (желательно с модулем) так же, как PHP имел подготовленные операторы, которые защищали от них.

Если так, то как? Если нет, Какие примеры могут обойти предоставленный мною код (см. Ниже).


Некоторый контекст:

Я делаю веб-приложение с внутренним стеком, состоящим из Node.js + MySql, используя модуль node-mysql . С точки зрения удобства использования, модуль великолепен, но он еще не реализовал что-то похожее на PHP Подготовленные выражения (хотя я знаю, что он находится на todo ).

Насколько я понимаю, реализация подготовленных операторов в PHP, среди прочего, очень помогла в предотвращении SQL-инъекций. Однако меня беспокоит то, что мое приложение node.js может быть открыто для подобных атак, даже с экранированием строки, предоставленным по умолчанию (как в фрагменте кода ниже).

node-mysql, кажется, является самым популярным соединителем mysql для node.js, поэтому мне было интересно, что другие люди могут делать (если вообще что-то), чтобы объяснить эту проблему - или если это даже проблема с node.js для начала (не уверен, как это было бы, так как ввод на стороне пользователя/клиента).

Должен ли я переключиться на node-mysql-native на данный момент, поскольку он предоставляет подготовленные операторы? Я не решаюсь сделать это, потому что он не так активен, как node-mysql (хотя это может означать, что он завершен).

Ниже приведен фрагмент кода регистрации пользователя, который использует модуль sanitizer вместе с подготовленным синтаксисом, похожим на операторы узла-mysql (который, как я упоминал выше, выполняет экранирование символов), чтобы предотвратить межсайтовый скриптинг и sql инъекции соответственно:

// 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?
   });
73
funseiki

Библиотека node-mysql автоматически выполняет экранирование при использовании, как вы уже делаете. Смотрите https://github.com/felixge/node-mysql#escaping-query-values ​​

48
Michael Pratt

Я понимаю, что это старый пост, но кажется, что ответ никогда не был отмечен, поэтому я добавлю его туда.

Что касается тестирования, является ли используемый вами модуль безопасным или нет, есть несколько маршрутов, которые вы можете выбрать. Я коснусь плюсов/минусов каждого, чтобы вы могли принять более обоснованное решение.

В настоящее время нет никаких уязвимостей для используемого вами модуля, однако это часто может привести к ложному ощущению безопасности, поскольку вполне может быть уязвимость, которая в настоящее время использует используемый вами модуль/программный пакет, и вы не будете предупреждены к проблеме, пока поставщик не применяет исправление/исправление.

  1. Чтобы быть в курсе уязвимостей, вам нужно следить за списками рассылки, форумами, IRC и другими обсуждениями, связанными с хакерскими атаками PRO: Вы можете часто узнавать о потенциальных проблемах в библиотеке до того, как поставщик предупрежден или выпустил исправление/исправление для устранения потенциальной возможности атаки на их программное обеспечение ........ CON: это может быть очень трудоемким и ресурсоемким. Если вы пойдете по этому пути, то бот будет использовать RSS-каналы, синтаксический анализ журналов (журналы чата IRC) и веб-скребок с использованием ключевых фраз (в данном случае node-mysql-native), а уведомления могут помочь сократить время, затрачиваемое на троллинг этих ресурсов.

  2. Создайте фаззер, используйте fuzzer или другую инфраструктуру уязвимостей, такую ​​как metasploit , sqlMap etc., чтобы помочь в тестировании проблем, которые поставщик, возможно, не искал . PRO: Это может оказаться надежным методом обеспечения приемлемого уровня того, является ли внедряемый вами модуль/программное обеспечение безопасным для публичного доступа CON: Это также становится трудоемким и дорогостоящим. Другая проблема возникнет из-за ложных срабатываний, а также из-за необразованного анализа результатов, если проблема существует, но не замечена.

На самом деле безопасность и безопасность приложений в целом могут занимать очень много времени и ресурсов. Менеджеры всегда будут использовать формулу для определения экономической эффективности (трудовые ресурсы, ресурсы, время, оплата и т.д.) Выполнения двух указанных выше вариантов.

В любом случае, я понимаю, что это не тот ответ «да» или «нет», на который можно было надеяться, но я не думаю, что кто-то может дать его вам, пока они не проведут анализ рассматриваемого программного обеспечения.

9
jas-

В библиотеке есть раздел в файле readme о побеге. Это Javascript-native, поэтому я не предлагаю переключаться на node-mysql-native . В документации изложены следующие рекомендации по экранированию:

Edit:node-mysql-native также является чисто Javascript-решением.

  • Числа остались нетронутыми
  • Логические значения преобразуются в строки true/false
  • Объекты Date преобразуются в строки YYYY-mm-dd HH:ii:ss
  • Буферы преобразуются в шестнадцатеричные строки, например X'0fa5'
  • Строки благополучно экранированы
  • Массивы превращаются в список, например ['a', 'b'] превращается в 'a', 'b'
  • Вложенные массивы превращаются в сгруппированные списки (для массовых вставок), например [['a', 'b'], ['c', 'd']] превращается в ('a', 'b'), ('c', 'd')
  • Объекты превращаются в пары key = 'val'. Вложенные объекты преобразуются в строки.
  • undefined/null преобразуются в NULL
  • NaN/Infinity остаются как есть. MySQL не поддерживает их, и попытка вставить их в качестве значений вызовет ошибки MySQL, пока не будет реализована поддержка.

Это позволяет вам делать такие вещи:

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'
});

Так же как и это:

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'
});

Помимо этих функций, вы также можете использовать функции escape:

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

Чтобы избежать идентификаторов запроса:

mysql.escapeId(identifier);

И как ответ на ваш комментарий к подготовленным заявлениям:

С точки зрения удобства использования, модуль великолепен, но он еще не реализовал что-то похожее на подготовленные операторы PHP.

Подготовленные операторы находятся в списке todo для этого соединителя, но этот модуль, по крайней мере, позволяет указывать пользовательские форматы, которые могут быть очень похожи на подготовленные операторы. Вот пример из 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));
};

Это изменяет формат запроса соединения, поэтому вы можете использовать такие запросы:

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

Я знаю, что этот вопрос старый, но для всех, кто интересуется, Mysql-native устарел, поэтому он стал MySQL2 , то есть новым модулем, созданным с помощью команды исходного модуля MySQL. Этот модуль имеет больше функций, и я думаю, что он имеет то, что вы хотите, так как он подготовил операторы (используя .execute ()), как в PHP для большей безопасности. 

Это также очень активно (последнее изменение было от 2-1 дней), я не пробовал раньше, но я думаю, что это то, что вы хотите, и даже больше.

1
Boy pro

Самый простой способ - обработать все взаимодействия с вашей базой данных в своем собственном модуле, который вы экспортируете в свои маршруты. Если ваш маршрут не имеет контекста базы данных, SQL все равно не сможет его коснуться.

0
Bird Dad