Можно ли предотвратить SQL-инъекции в Node.js (желательно с помощью модуля) так же, как в PHP были подготовленные операторы, защищающие от них.
Если да, то как? Если нет, то каковы некоторые примеры, которые могут обойти предоставленный мной код (см. Ниже).
Некоторый контекст:
Я создаю веб-приложение с внутренним стеком, состоящим из Node.js + MySql, с использованием модуля node-mysql . С точки зрения юзабилити, модуль является большим, но это еще не реализовано что - то похожее на РНР Подготовленные заявления (хотя я знаю , что это на TODO ).
Насколько я понимаю, реализация подготовленных операторов PHP, помимо прочего, очень помогла в предотвращении инъекций SQL. Однако меня беспокоит, что мое приложение node.js может быть открыто для подобных атак, даже с экранированием строки, предоставленным по умолчанию (как в фрагменте кода ниже).
node-mysql, кажется, является самым популярным соединителем mysql для node.js, поэтому мне было интересно, что другие люди могут делать (если что-то), чтобы учесть эту проблему - или это даже проблема с node.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?
});
источник
В библиотеке есть раздел в файле readme, посвященный экранированию. Это Javascript-native, поэтому я не предлагаю переходить на node-mysql-native . В документации изложены следующие рекомендации по экранированию:
Изменить: node-mysql-native также является решением на чистом Javascript.
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' });
Помимо этих функций, вы также можете использовать escape-функции:
connection.escape(query); mysql.escape(query);
Чтобы избежать идентификаторов запроса:
mysql.escapeId(identifier);
И в ответ на ваш комментарий к подготовленным заявлениям:
Подготовленные операторы находятся в списке задач для этого коннектора, но этот модуль, по крайней мере, позволяет вам указывать настраиваемые форматы, которые могут быть очень похожи на подготовленные операторы. Вот пример из ридми:
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");
источник
Я понимаю, что это более старый пост, но кажется, что ответ никогда не был отмечен, поэтому я брошу его там.
Что касается тестирования того, является ли модуль, который вы используете, безопасным или нет, вы можете выбрать несколько маршрутов. Я коснусь плюсов и минусов каждого, чтобы вы могли принять более обоснованное решение.
В настоящее время нет никаких уязвимостей для модуля, который вы используете, однако это часто может привести к ложному чувству безопасности, так как вполне может быть уязвимость, которая в настоящее время использует модуль / программный пакет, который вы используете, и вы не будете предупреждены к проблеме, пока поставщик не применит исправление / патч.
Чтобы быть в курсе уязвимостей, вам нужно будет подписаться на списки рассылки, форумы, IRC и другие обсуждения, связанные с взломом. PRO: Вы можете часто узнавать о потенциальных проблемах в библиотеке до того, как поставщик был предупрежден или выпустил исправление / патч, чтобы устранить потенциальную возможность атаки на его программное обеспечение. ПРОТИВ: Это может занять очень много времени и ресурсов. Если вы действительно пойдете по этому пути, бот будет использовать RSS-каналы, парсинг журналов (журналы IRC-чатов) и / или веб-парсер с использованием ключевых фраз (в данном случае node-mysql-native) и уведомления могут помочь сократить время, потраченное на троллинг этих ресурсов.
Создайте фаззер, используйте фаззер или другую структуру уязвимостей, например metasploit , sqlMap и т. Д., Чтобы помочь проверить проблемы, которые поставщик, возможно, не искал. ЗА: Это может оказаться верным методом проверки на приемлемом уровне того, безопасен ли модуль / программное обеспечение, которое вы внедряете, для публичного доступа. ПРОТИВ: Это также требует много времени и средств. Другая проблема будет возникать из-за ложных срабатываний, а также из-за необразованного анализа результатов, когда проблема присутствует, но не замечена.
На самом деле безопасность и безопасность приложений в целом могут потребовать очень много времени и ресурсов. Одна вещь, которую менеджеры всегда будут использовать, - это формула для определения экономической эффективности (рабочая сила, ресурсы, время, оплата и т. Д.) Выполнения двух вышеуказанных вариантов.
В любом случае, я понимаю, что это не ответ «да» или «нет», на который, возможно, надеялись, но я не думаю, что кто-то может дать вам это, пока не проведет анализ рассматриваемого программного обеспечения.
источник
Я знаю, что этот вопрос старый, но для всех, кто интересуется, Mysql-native устарел, поэтому он стал MySQL2 который представляет собой новый модуль, созданный с помощью команды исходного модуля MySQL. Этот модуль имеет больше функций, и я думаю, что он имеет то, что вы хотите, поскольку он подготовил операторы (с помощью.execute ()), как в PHP, для большей безопасности.
Он также очень активен (последнее изменение было от 2 до 1 дня). Я не пробовал его раньше, но я думаю, что это то, что вы хотите, и многое другое.
источник
Самый простой способ - обрабатывать все взаимодействия с базой данных в собственном модуле, который вы экспортируете в свои маршруты. Если ваш маршрут не имеет контекста базы данных, SQL все равно не сможет его коснуться.
источник