Внедрение SQL и предварительная компиляция Mybatis предотвращают внедрение SQL

MySQL

Что такое SQL-инъекция? ?

Так называемая SQL-инъекция заключается в том, чтобы заставить сервер выполнять вредоносные SQL-команды, вставляя SQL-команды в строку запроса отправки веб-формы или URL-адрес запроса страницы. В частности, это возможность использовать существующие приложения для внедрения (вредоносных) команд SQL в выполнение фонового ядра базы данных, и он может получать (вредоносные) операторы SQL в веб-форме, чтобы получить уязвимость безопасности на веб-сайте. вместо того, чтобы выполнять операторы SQL, как задумал дизайнер.

Практический пример Есть окно входа в систему следующим образом:

在这里插入图片描述
Видно, что помимо пароля учетной записи есть еще поле ввода названия компании.По форме поля ввода несложно вывести способ написания SQL следующим образом:

SELECT * From table_name WHERE name=‘XX’ and password=‘YY’ and corporate=‘ZZ’

Как это сделать, ?

在这里插入图片描述
верификации нет, поэтому пароль от аккаунта не заполняем, прямо в конце добавляем или 1=1 —

Посмотрите на комбинацию с приведенным выше 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-инъекции, когда обработка не выполняется. Вы говорите, как это предотвратить, тогда я могу только сказать вам трагически, что вы должны вручную обрабатывать и фильтровать входящий контент. Например, чтобы определить, является ли длина входных параметров нормальной (оператор инъекции обычно очень длинный), и для более точной фильтрации можно проверить, входят ли входные параметры в ожидаемый набор параметров.