2013-04-03 4 views
54

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

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


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

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

С моей точки зрения, реализация PHP готовых заявлений, среди прочего, helped greatly в предотвращении инъекций SQL. Я обеспокоен тем, что приложение node.js может быть открыто для подобных атак, even with the string escaping provided by default (как в приведенном ниже фрагменте кода).

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

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

Ниже приведен фрагмент кода регистрации пользователя, который использует модуль sanitizer, а также подготовленный оператор-подобный синтаксис node-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? 
    }); 

ответ

37

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

+1

Как я упоминал в своем сообщении, я знаю, что библиотека ускользает от символов, но меня больше беспокоят последствия безопасности, если я не переключусь на библиотеку, в которой реализованы подготовленные операторы, т.е. есть ли SQL-инъекция, которая может происходят с тем, что я сейчас делаю? – funseiki

+0

Экранирование символов предотвращает SQL-инъекцию. Инъекции возникают, когда символы не экранируются, а злоумышленники могут использовать это для закрытия запроса и запуска нового, например, для удаления таблицы или вставки поддельной записи. С экранированными символами это невозможно. [Wikipedia] (http://en.wikipedia.org/wiki/SQL_injection) содержит дополнительную информацию о SQL Injection. –

+3

Но предотвращает ли это все инъекции SQL? [Этот ответ] (http://stackoverflow.com/a/12118602/865883) предлагает не (по крайней мере, для PHP + MySQL), и подразумевает, что это подготовленные заявления PHP. Опять же, это в контексте PHP. – funseiki

8

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

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

  • Число осталось нетронутым
  • Booleans преобразуется в true/false строк
  • Даты объектов преобразуются в 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' 
}); 

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

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

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

mysql.escapeId(identifier); 

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

С точки зрения юзабилити, модуль является большим, но это еще не реализовано нечто похожее на Подготовленные заявления РНР.

Подготовленные заявления на todo список для этого разъема, но этот модуль по крайней мере, позволяет определить пользовательские форматы, которые могут быть очень похожи на подготовленные заявления. Вот пример из ридх:

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"); 
+0

Благодарим за отзыв - я знаю стиль, подобный подготовленному. Однако под этим символом скрываются символы. Смотрите: ["Однако на самом деле он просто использует тот же connection.escape()"] (https://github.com/felixge/node-mysql#escaping-query-values). Насколько я не использую node-mysql-native: это то, с чем я борюсь. Если node-mysql-native реализует подготовленные операторы и его реализации предотвращает SQL-инъекции, не должен ли я переключаться до тех пор, пока узел-mysql не будет иметь их? – funseiki

+0

Это вопрос курицы и яйца. Я не активно развиваю свой драйвер, потому что большинство людей используют @ felixge. Вероятно, я попытаюсь найти некоторое время для подготовки подготовленных операторов к node-mysql, поскольку это действительно дает некоторые преимущества в производительности (и, возможно, делает более сложными SQL-инъекции). Не стесняйтесь комментировать/отправлять сообщения, если вы решите дать ему ответ –

+0

@funseiki Я уверен, что подготовленные операторы будут лучшим решением, но я уверен, что экранирование предотвратит SQL-инъекции.Поскольку сам модуль поддерживается Joyent, модуль активен и, очевидно, тщательно проверен. Если этот модуль не был готов к производству, то я не думаю, что в прошлом месяце модуль имел бы в среднем 1000 загрузок в день. Обратите внимание, что node-mysql-native составляет 6 месяцев с момента его разработки, а node-mysql очень активен, и несколько человек работают над ним. – hexacyanide

8

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

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

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

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

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

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

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