Что такое SQL-инъекция? ?
Так называемая SQL-инъекция заключается в том, чтобы заставить сервер выполнять вредоносные SQL-команды, вставляя SQL-команды в строку запроса отправки веб-формы или URL-адрес запроса страницы. В частности, это возможность использовать существующие приложения для внедрения (вредоносных) команд SQL в выполнение фонового ядра базы данных, и он может получать (вредоносные) операторы SQL в веб-форме, чтобы получить уязвимость безопасности на веб-сайте. вместо того, чтобы выполнять операторы SQL, как задумал дизайнер.
Практический пример Есть окно входа в систему следующим образом:
SELECT * From table_name WHERE name=‘XX’ and password=‘YY’ and corporate=‘ZZ’
Как это сделать, ?
Посмотрите на комбинацию с приведенным выше SQL, она становится следующей:
SELECT * From table_name WHERE name=’’ and password=’’ and corporate=’’ or 1=1-’
Как видно из кода, первая половина одинарных кавычек закрыта, вторая половина одинарных кавычек закомментирована знаком "-", и есть условие "1=1", которое всегда устанавливается в середина, что приводит к успешному входу в систему любого персонажа. .
Важное напоминание
Не думайте, что проверки в поле ввода достаточно.Не забывайте, что когда мы отправляем форму в Интернете, мы можем напрямую получить доступ к прошлому, имитируя URL-адрес, минуя предыдущую проверку. Следовательно, это должен быть сервер или данные для проверки, чтобы эффективно предотвратить это.
(1) Проверить легитимность пользовательского ввода;
(2) Зашифруйте и сохраните имя пользователя, пароль и другие данные.
(3) Предварительная обработка SQL.
(4) Использование хранимых процедур для реализации запросов, хотя и не рекомендуется, также является методом.
Как предотвращается предварительная обработка MySQL?
В качестве полуавтоматической инфраструктуры уровня сохраняемости среда MyBatis требует от нас ручного написания своих операторов SQL.Конечно, нам нужно предотвратить внедрение SQL в это время. По сути, SQL MyBatis представляет собой функцию с «вводом + выводом», похожую на структуру функции, а именно:
<select id="getBlogById" resultType="Blog" parameterType=”int”>
SELECT id,title,author,content
FROM blog
WHERE id=#{id}
</select>
Здесь параметрType представляет тип входного параметра, а resultType представляет тип выходного параметра. В ответ на вышеизложенное, если мы хотим предотвратить внедрение SQL, естественно работать с входными параметрами. Желтая подсветка в приведенном выше коде — это часть, где входные параметры объединены в SQL.После передачи параметров распечатайте выполненный оператор SQL, и вы увидите, что SQL выглядит следующим образом:
SELECT id,title,author,content FROM blog WHERE id = ?
Независимо от того, какие параметры введены, напечатанный SQL будет таким. Это связано с тем, что MyBatis включает функцию предварительной компиляции.Перед выполнением SQL приведенный выше SQL будет отправлен в базу данных для компиляции; при выполнении скомпилированный SQL можно использовать напрямую, а заполнитель "?" можно заменить. Поскольку SQL-инъекция может работать только в процессе компиляции, этот способ позволяет избежать проблемы с SQL-инъекцией.
[Принцип низкоуровневой реализации] Как MyBatis выполняет предварительную компиляцию SQL? На самом деле в основе фреймворка лежит класс PreparedStatement в JDBC. PreparedStatement является подклассом знакомого нам Statement. Его объект содержит скомпилированные операторы SQL. Этот «подготовленный» подход не только повышает безопасность, но и повышает эффективность при многократном выполнении одного и того же SQL. Причина в том, что SQL уже скомпилирован и не нуждается в повторной компиляции при повторном выполнении.
Сказав это, можем ли мы предотвратить внедрение SQL с помощью MyBatis? Конечно нет, смотрите код ниже:
<select id="getBlogById" resultType="Blog" parameterType=”int”>
SELECT id,title,author,content
FROM blog
WHERE id=${id}
</select>
При ближайшем рассмотрении формат встроенного параметра изменился с "#{xxx}" на "${xxx}". Если мы присвоим параметру «id» значение «3», SQL будет напечатан следующим образом:
SELECT id,title,author,content FROM blog WHERE id = 3
(Контрастный пример выше был добавлен мной для контраста с предыдущим примером.)
<select id="orderBlog" resultType="Blog" parameterType=”map”>
SELECT id,title,author,content
FROM blog
ORDER BY ${orderParam}
</select>
При ближайшем рассмотрении формат встроенного параметра изменился с "#{xxx}" на "${xxx}". Если мы присвоим параметру «orderParam» значение «id», SQL выведет следующее:
SELECT id,title,author,content FROM blog ORDER BY id
Очевидно, что это не может предотвратить внедрение SQL. В MyBatis,“${xxx}”
Параметры в этом формате будут напрямую участвовать в компиляции SQL, так что инъекционных атак не избежать. Но когда дело доходит до динамических имен таблиц и имен столбцов, вы можете использовать только“${xxx}”
такой формат параметра. Следовательно, такие параметры необходимо обрабатывать вручную в коде, чтобы предотвратить внедрение.
[Заключение] При написании оператора сопоставления MyBatis попробуйте использовать“#{xxx}”
такой формат. Если вам нужно использовать“${xxx}”
Такие параметры следует фильтровать вручную, чтобы предотвратить атаки SQL-инъекций.
#{}:相当于JDBC中的PreparedStatement
${}:是输出变量的值
Проще говоря, #{} предварительно скомпилирован и безопасен; ${} не предварительно скомпилирован, он просто принимает значение переменной, это небезопасно, и есть SQL-инъекция.
Если мы используем порядок по оператору${}
, то существует опасность SQL-инъекции, когда обработка не выполняется. Вы говорите, как это предотвратить, тогда я могу только сказать вам трагически, что вы должны вручную обрабатывать и фильтровать входящий контент. Например, чтобы определить, является ли длина входных параметров нормальной (оператор инъекции обычно очень длинный), и для более точной фильтрации можно проверить, входят ли входные параметры в ожидаемый набор параметров.