Безопасно ли избегать таких запросов SQL? - PullRequest
0 голосов
/ 12 ноября 2018

В настоящее время я работаю над внутренним скриптом NodeJS, который анализирует входящие HTTP-запросы на запись и чтение из базы данных MySQL для работы.Я пытался защитить его от SQL-инъекций, используя своего рода двухслойную защиту.

Для записи в базу данных пользователю необходимо предоставить valid JSON.Вот как ключи JSON должны быть , чтобы скрипт записывал в БД.Если это не так, запрос будет отменен.

{
    "uuid": "1234-5678-abcd-efgh",
    "product_id": 6,
    "product_extras": "color=red",
    "product_count": 2,
    "buyer_name": "X Y",
    "shipping_address": "XY Street 5"
}

Первый слой, который проверяет этот вход, является очень простым черным списком.Здесь переменная USER_INPUT - это приведенный выше JSON, который уже прошел процесс проверки.

let BLACKLIST = ["DROP ", "DELETE ", "INSERT ", "UPDATE ", "SELECT ", "WHERE ", "ALTER "];
let dont_execute = false;

for(var i = 0; i < BLACKLIST.length; i++) {   
    if(JSON.stringify(USER_INPUT).toUpperCase().includes(BLACKLIST[i].toUpperCase())) {
        console.log("\x1b[31mreceived blacklisted command - aborting");
        dont_execute = true;
        return false;
    }
}

После этой проверки, если dont_execute все еще имеет значение false, будет вызван второй уровень и запрос будет экранирован и отправлен следующим образом:

// setting.sqlconnection.table_name is equal to "orders" in this case. Also this variable can't be changed or specified by the user. It's pulled from a settings.json file

sql.sendQuery("INSERT INTO " + setting.sqlconnection.table_name + " (uuid, productid, orderid, productextras, productcount, buyername, shippingaddress) VALUES (" + sqlconnection.escape(uuid) + ", " + sqlconnection.escape(parseddata.product_id) + ", " + null + ", " + sqlconnection.escape(parseddata.product_extras) + ", " + sqlconnection.escape(parseddata.product_count) + ", " + sqlconnection.escape(parseddata.buyer_name) + ", " + sqlconnection.escape(parseddata.shipping_address) + ")");





Я пробовал много разных инъекций, подобных этой:

{
    "uuid": "1234-5678-abcd-efgh",
    "product_id": 6,
    "product_extras": "color=red",
    "product_count": 2,
    "buyer_name": "X Y",
    "shipping_address": "');DROP orders;--"
}

И так же, как яОжидается, что это не сработало, потому что прежде всего это было отражено в первом слое черного списка.Но после его отключения только для того, чтобы проверить все, весь SQL-запрос был просто интерпретирован как строка, поскольку апостроф был экранирован (' стал \'), и это именно то, что я хотел.Насколько мне известно, запрос, который будет отправлен с зараженным SLQI JSON, будет выглядеть следующим образом:

INSERT INTO orders (guid, productid, orderid, productextras, productcount, buyername, shippingaddress) VALUES ("1234-5678-abcd-efgh", 6, null, "color=red", 2, "X Y", "\');DROP orders--")

Но проблема в том, что, показав это своему боссу, он сказал, чтоне быть в безопасности, и он все еще уязвим для SQLI.Поэтому мой вопрос: прав ли он, и если да, то что я могу сделать, чтобы улучшить его.




Дополнительная информация:
Я использую пакет npm mysqlдля подключения к базе данных
Я использую XAMPP с MySQL для локального размещения базы данных




Извините, если не могу предоставить больше информации, но я довольноуверен, что мне не разрешено публиковать больше материалов, чем это.

1 Ответ

0 голосов
/ 14 ноября 2018

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

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

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

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

Вредные данные поступают не только от пользователей. Он может поступать из файлов, из веб-сервисов, из документов JSON. Это может даже прийти из вашей собственной базы данных! Любой контент, который может содержать странные символы, может вызвать внедрение SQL.

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

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

Когда-нибудь видели таблицу в базе данных электронной коммерции с именем ORDER? Это может привести к путанице в SQL, поскольку ORDER является зарезервированным словом. Вы должны разделять имена таблиц обратными галочками на случай, если они являются зарезервированными для SQL словами или содержат знаки препинания или пробелы.

Вот пример добавления обратных галочек вокруг имени таблицы:

sql.sendQuery("INSERT INTO `" + setting.sqlconnection.table_name + "` (uuid, ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...