SQL-инъекция в функции Postgres против подготовленных запросов

30

В Postgres подготовленные запросы и пользовательские функции эквивалентны как механизм защиты от внедрения SQL ?
Есть ли конкретные преимущества в одном подходе по сравнению с другим?

mickeyf_supports_Monica
источник

Ответы:

36

Это зависит.

Функции SQL

С LANGUAGE sqlответом, как правило, да .

Переданные параметры обрабатываются как значения, и внедрение SQL невозможно, если вы не вызываете небезопасные функции из тела и не передаете параметры.

PL / pgSQL функции

С LANGUAGE plpgsqlответом, как правило, да .

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

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

Для динамического SQL желательно передавать значения как значения с помощью:

Делает SQL-инъекцию невозможной на главной.

Если вы объединяете значения в строке SQL, используйте:

Безопасно заключает строки в одинарные кавычки , что позволяет избежать синтаксических ошибок и внедрения SQL.

Параметры процесса, которые должны обрабатываться как идентификаторы в строке SQL с помощью:

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

Связанный:

Никогда не создавайте строку из пользовательского ввода и выполняйте. Это включает в себя идентификаторы, непосредственно переданные пользователем или полученные из системного каталога. При построении динамического SQL все должно обрабатываться как вводимые пользователем данные и безопасно цитироваться!

Подробнее о влиянии на производительность в этом связанном ответе:

Основы SQL-инъекции:

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

Эрвин Брандштеттер
источник
Итак, в итоге: если 1) я использую только язык sql, я в безопасности, 2) если я использую plpgslq, но не выполняю, я в безопасности, 3) если я использую plpgsql и выполняю, но без идентификаторов и% s или% L в случае необходимости, я в безопасности, или 4) если я использую plpgsql и выполняю и идентификаторы, но% I или quote_ident, в зависимости от ситуации, я в безопасности. Правильный?
mickeyf_supports_Monica
@mickeyf: в основном да. Кроме того, используйте USINGусловие для передачи значений, EXECUTEкогда это возможно. Вы можете вызвать функцию PL / pgSQL из функции SQL и передать параметры. Итак, чтобы быть абсолютно правильным, вы в безопасности, если вы не вызываете небезопасные функции прямо или косвенно. Если все ваши функции выполнены правильно, это не может произойти.
Эрвин Брандштеттер,