Не используйте парсинг SQL для создания режима «только для чтения» в Query Runner

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

Если вы создаете инструмент для выполнения SQL-запросов, вам нужен режим «только для чтения». Вы хотите предотвратить случайный UPDATE, который может удалить ваши данные. Вашей первой мыслью может быть блокировка таких слов, как DELETE или DROP.

Не делайте этого.

Проверки строк легко обойти. Пользователь может использовать предложение WITH, чтобы скрыть DELETE. Можно использовать комментарии, чтобы спрятать команды. Можно вызвать функцию, которая записывает данные в таблицу. В итоге вы окажетесь в проигрышной игре в «прихлопни крота» (whack-a-mole).

Позвольте базе данных самой заниматься безопасностью.

В Postgres есть встроенная функция для этого. Вы можете объявить транзакцию только для чтения. После этого сервер будет отклонять любые команды записи. Это распространяется на CTE, функции и DDL.

Вот как правильно реализовать это на Python:

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

Безопасность состоит из двух частей:

  1. Защита от записи: используйте транзакции только для чтения.
  2. Защита от злоупотребления ресурсами: используйте таймауты и лимиты строк.

Даже запрос «только для чтения» может обрушить вашу систему из-за огромного JOIN. Транзакция «только для чтения» останавливает запись, но она не предотвращает чрезмерное потребление ресурсов. Чтобы сделать ad-hoc SQL безопасным, вам нужны оба механизма.

Перестаньте парсить SQL. Попросите базу данных выполнять свою работу.

Источник: https://dev.to/hitoshi1964/dont-parse-sql-to-make-a-query-runner-read-only-b62