Как минимизировать риск внедрения SQL в нисходящие сервисы в сервисе golang? - PullRequest
0 голосов
/ 19 февраля 2019

Я пишу веб-службу с внешним видом на golang, которая позволяет пользователям запрашивать информацию о своих учетных записях, которая распределена по нескольким внутренним устаревшим службам.

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

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

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

Что я могу сделать в своем коде golang для очистки пользовательского ввода максимально , чтобы минимизировать риск проскальзывания SQL-инъекции?В конечном итоге это является мерой ограничения, пока все последующие вызовы БД не могут быть проверены для обеспечения безопасности инъекций.

Редактировать: пользовательский ввод может для всех практических целей быть произвольной строкой, но он не должен когда-либо быть исполняемым кодом.Мой сервис ожидает от пользователя значения полей, а не кода.

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

Добавить к ответу Билла, охватывающему ввод данных.Чтобы обеспечить санацию выводимых данных, скажем, веб-службы, посмотрите html / template :

Шаблон пакета (html / template) реализует управляемые данными шаблоны длягенерирование HTML-вывода, защищенного от внедрения кода.

0 голосов
/ 19 февраля 2019

На прошлой работе я поддерживал сервис для нашего сервиса, который разрешал специальные запросы.Это позволило менеджерам запрашивать отчеты без необходимости ждать недели для развертывания кода (в те странные дни, когда развертывание занимало недели).

Мы НЕ поддерживали специальные запросы отчетов, поскольку служба принимала произвольные строки в качестве входных данных.и выполнить их как 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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...