На прошлой работе я поддерживал сервис для нашего сервиса, который разрешал специальные запросы.Это позволило менеджерам запрашивать отчеты без необходимости ждать недели для развертывания кода (в те странные дни, когда развертывание занимало недели).
Мы НЕ поддерживали специальные запросы отчетов, поскольку служба принимала произвольные строки в качестве входных данных.и выполнить их как SQL.Это ужасно небезопасно, как я уверен, вы знаете.
То, как это работало, заключалось в том, что запросы отчетов сохранялись в базе данных вместе с необходимым количеством параметров запроса.
CREATE TABLE ManagerQueries (
id INT PRIMARY KEY,
query TEXT NOT NULL,
description TEXT NOT NULL,
num_params TINYINT UNSIGNED NOT NULL DEFAULT 0
);
INSERT INTO ManagerQueries
SET query = 'SELECT COUNT(*) FROM logins WHERE user_id = {0} AND created_at > {1}',
description = 'Count a given user logins since a date',
num_params = 2;
Интерфейс менеджера может запросить запрос по его первичному ключу, НЕ указав произвольную строку SQL в веб-запросе.
Только администратор базы данных и, возможно, другие разработчики или менеджерыкто знал, как писать безопасные запросы, мог добавлять новые запросы в этот репозиторий, поэтому была некоторая уверенность в том, что запросы были проверены и проверены.
Когда запрос отчета запрашивался через пользовательский интерфейс, это заставляло пользователяпредоставить значения для параметров запроса.В нашем случае он считал SQL из базы данных, сделал prepare()
, а затем связал значения для execute()
.Таким образом, защита от внедрения SQL была удовлетворена.
В вашем случае ваш код может не иметь прямого доступа к базе данных устаревшей службы, поэтому вы не можете выполнять подготовку / выполнение и использовать связанные параметры.Вы должны отправить статический запрос с интегрированными значениями.
На других языках вы можете сделать любое строковое значение безопасным для интерполяции в запрос SQL, экранируя .См. Функцию MySQL C API mysql_real_escape_string () .
Числовые значения еще проще.Вам не нужно ничего избегать, вы просто должны убедиться, что числовое значение является подлинным числовым.Как только вы приведете динамическое значение к числовому, можно безопасно интерполировать обратно в любую строку SQL.
К сожалению, я не думаю, что пакеты SQL golang поддерживают какую-либо экранирующую функцию.Это было запрошено как функция, но насколько я знаю, пока нет поддерживаемой реализации.Смотрите обсуждение здесь: https://github.com/golang/go/issues/18478
Так что вам, возможно, придется реализовать свою собственную функцию экранирования.Например, вы можете смоделировать его после официальной реализации MySQL C: https://github.com/mysql/mysql-server/blob/8.0/mysys/charset.cc#L716
Обратите внимание, что это немного сложнее, чем просто использование подстановки регулярных выражений, поскольку вам необходимо учитывать многобайтовые наборы символов.