Проблема
Нам нужно защищаться от sql-атаки «WAITFOR DELAY» в нашем java-приложении.
Фон
[Это долго. Перейти к «Решение?» раздел ниже, если вы спешите]
Наше приложение в основном использует подготовленные операторы и вызываемые операторы (хранимые процедуры) при доступе к базе данных.
В некоторых местах мы динамически строим и выполняем запросы для выбора. В этой парадигме мы используем объект критерия для построения запроса в зависимости от критериев пользовательского ввода. Например, если пользователь указал значения для first_name и last_name, запрос результата всегда будет выглядеть примерно так:
SELECT first_name,last_name FROM MEMBER WHERE first_name ='joe' AND last_name='frazier'
(В этом примере пользователь указал бы «joe» и «frazier» в качестве своих входных значений. Если бы у пользователя было больше или меньше критериев, у нас были бы более длинные или более короткие запросы. Мы обнаружили, что этот подход проще чем использование подготовленных операторов и более быстрая / более производительная, чем хранимые процедуры).
Атака
Аудит уязвимости сообщил об ошибке внедрения SQL. Злоумышленник ввел значение 'frazier WAITFOR DELAY '00: 00: 20' для параметра 'last_name', в результате чего получилось следующее sql:
SELECT first_name,last_name FROM MEMBER WHERE first_name ='joe' AND last_name='frazier' WAITFOR DELAY '00:00:20'
Результат: запрос выполняется успешно, но для его выполнения требуется 20 секунд. Злоумышленник может связать все ваши подключения к базе данных в пуле базы данных и эффективно закрыть ваш сайт.
Некоторые наблюдения об этой атаке "ЗАДЕРЖКА ОЖИДАНИЯ"
Я думал, что, поскольку мы использовали Statement executeQuery (String), мы были бы защищены от внедрения SQL. executeQuery (String) не будет выполнять DML или DDL (удаляет или удаляет). И executeQuery (String) блокирует точки с запятой, поэтому парадигма 'таблиц Бобби' потерпит неудачу (т. Е. Пользователь вводит "frazier; DROP TABLE member" для параметра. См. http://xkcd.com/327/)
Атака «WAITFOR» отличается одним важным аспектом: WAITFOR изменяет существующую команду «SELECT» и не является отдельной командой.
Атака работает только на «последний параметр» в результирующем запросе. то есть 'WAITFOR' должен встречаться в самом конце оператора sql
Решение, дешевый взлом или оба?
Наиболее очевидное решение заключается в простом добавлении «И 1 = 1» в предложение where.
Полученный sql сразу завершается неудачей и мешает атакующему:
SELECT first_name,last_name FROM MEMBER WHERE first_name ='joe' AND last_name='frazier' WAITFOR DELAY '00:00:20' AND 1=1
Вопросы
- Это жизнеспособное решение для атаки WAITFOR?
- Защищает ли он от других подобных уязвимостей?
- Я думаю, что лучший вариант влечет за собой использование подготовленных заявлений. Больше работы, но менее уязвимо.