Статья основана на двадцать втором видео из 31 темы курса SQL 2.0 — PL/pgSQL в PostgreSQL от Аристова Евгения, который является логическим продолжением курса SQL c 0. Ссылки на видео на платформах RUTUBE и VK video.
В данной статье подробно разбираются SQL инъекции, SQL injection, примеры защиты инъекции и её ключевые принципы.
В прошлой статье разбираются использование параметра search_path, ключевые моменты и рекомендации.
Презентация и исходники доступны по ссылке.
SQL injection
SQL инъекции в PostgreSQL — это уязвимости безопасности, возникающие при некорректной обработке пользовательского ввода, позволяющие злоумышленнику выполнить произвольный SQL-код.
-- УЯЗВИМЫЙ КОД
CREATE OR REPLACE FUNCTION vulnerable_login(username TEXT, password TEXT)
RETURNS BOOLEAN AS $$
DECLARE
query TEXT;
result BOOLEAN;
BEGIN
query := 'SELECT EXISTS(SELECT 1 FROM users WHERE username = ''' ||
username || ''' AND password = ''' || password || ''')';
EXECUTE query INTO result;
RETURN result;
END;
$$ LANGUAGE plpgsql;
-- АТАКА
SELECT vulnerable_login('admin', 'anything'' OR ''1''=''1');
-- Сгенерированный запрос, строка будет сконкатенирована:
-- SELECT EXISTS(SELECT 1 FROM users WHERE username = 'admin' AND password = 'anything' OR '1'='1')
Защита:
- Использование параметризованных запросов
- Использование форматирования с экранированием
- Валидация входных данных
- Использование защищенных процедур с нужными правами и отзыв прямого доступа
Основные ошибки:
-- Конкатенация строк для запросов
query := 'SELECT ... WHERE name = ''' || user_input || '''';
-- Динамический SQL без экранирования
EXECUTE 'SELECT ... WHERE name = ''' || user_input || '''';
-- Прямое использование пользовательского ввода
EXECUTE user_input;
Более подробно правильные варианты использования рассмотрим на следующей теме — динамический SQL.
Итоги
Ключевые принципы защиты:
- Всегда используйте параметризованные запросы
- Валидируйте и сканируйте все пользовательские данные
- Принцип минимальных привилегий для пользователей БД
- Экранируйте идентификаторы с помощью format() и %I
- Логируйте подозрительную активность
- Регулярно тестируйте на уязвимости
Больше примеров доступно на гитхабе и в видео.
В следующей статье мы разберём динамический SQL.
Добавить комментарий