Эффект подготовленного оператора против инъекции SQL - PullRequest
0 голосов
/ 09 мая 2018

Например, у меня есть код ниже:

import java.sql.*; ...
public void main (string[] args){ 
try {
 Class.forName („COM.ibm.db2.jdbc.net.DB2Driver“);} catch (ClassNotFoundException e) {//error handling}
try {
    String url = "jdbc:db2://host:6789/myDB2"
    Connection con = DriverManager.getConnection(url, "login", "password");
    PreparedStatement pStmt = con.prepareStatement("UPDATE PERS SET Salary=Salary*2.0 WHERE PNR=?"

    pStmt.setInt (1, 35);
    pStmt.executeUpdate();

    pStmt.setString (1, args[0]); 
    pStmt.executeUpdate();

    con.close();
    } catch (SQLException e) { //error handling}
}

Предположительно у нас есть таблица типа:

+--------+----------+-----------+
|PNR     |Name      |Salary     |
+--------+----------+-----------+
|34      |Tim       |20000      |
+--------+----------+-----------+
|35      |John      |45000      |
+--------+----------+-----------+

Мне трудно предсказать, что произойдет, если:

args[0]="35 OR Salary<100000" 

Разве команда setString не заменяет args[0] на 35 OR Salary < 100000, и тогда вся запись о зарплате удваивается?

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Подготовленные операторы на стороне сервера

Параметры SQL помогают избежать внедрения SQL, поскольку значение параметра вообще не сочетается с запросом SQL. Запрос SQL с заполнителями параметров отправляется на сервер MySQL, где он анализируется и анализируется. Он проверяет, что вы написали правильный синтаксис SQL, что таблицы и столбцы, на которые вы ссылаетесь, существуют, и у вас есть необходимые права для доступа к этим таблицам и столбцам.

Вот почему параметры не могут использоваться для имен таблиц или столбцов или другого синтаксиса. Потому что проверка происходит, когда параметры все еще остаются в качестве заполнителей. Значение параметров отправляется позже, поэтому проверка должна предполагать, что параметр должен заменить только одно скалярное значение в вашем запросе SQL.

После этого момента запрос сохраняется внутри сервера MySQL как нетекстовые структуры данных. Это больше не в SQL, это просто ряд внутренних объектов в коде MySQL. Места, в которых вы использовали ?, становятся элементами запроса, которые, как знает MySQL, должны быть снабжены значениями, прежде чем он сможет выполнить запрос.

Когда вы запускаете pStmt.executeUpdate() значения переменных, которые вы привязали к параметрам, отправляются на сервер MySQL. Они заполняются в качестве заполнителей в нетекстовом представлении запроса.

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

Параметры запроса - это надежный способ защиты от внедрения SQL.

эмулированные подготовленные отчеты

Некоторые драйверы реализуют «эмулированный» подготовленный оператор. Это означает, что он ничего не делает с запросом SQL, который вы передаете prepareStatement(), за исключением сохранения строки SQL в драйвере JDBC (на стороне клиента). В настоящее время он не отправляет запрос SQL на сервер.

Затем, когда вы запускаете executeUpdate(), ваши переменные интерполируются в местозаполнители параметров в строке SQL, и полная строка отправляется на сервер. Затем сервер MySQL анализирует комбинированный SQL-запрос, значения параметров и все. MySQL Server не может даже сказать, какие значения были литеральными значениями в исходном запросе SQL, а какие были объединены в качестве параметров. Все они представляются синтаксическому анализатору как буквальные значения.

В этом случае вы должны верить, что драйвер JDBC корректно экранирует, поэтому кавычки и другие символы в содержимом вашего параметра не могут смешивать анализатор SQL. Драйвер должен быть хорошо протестирован для обработки всех случаев, таких как специальные наборы символов, шестнадцатеричные символы кавычек и другие способы его обмануть.

0 голосов
/ 09 мая 2018

Это не вызовет проблем с внедрением SQL. Это будет переводить на:

UPDATE PERS SET Salary=Salary*2.0 WHERE PNR='35 OR Salary<100000'

Вставленные кавычки спасут вас от внедрения SQL. Я немного упрощаю. Реализация JDBC определяет, как именно PreparedStatement переводится в реальный запрос SQL. На самом деле это не обязательно переводит его в приведенный выше SQL. Но это один из способов предотвращения атак.

Осторожно, хотя. Если вы используете пользовательский ввод для создания SQL, вы все равно будете подвержены SQL-инъекциям. Пока вы используете пользовательский ввод только для вызова .setXYZ() параметров, вы будете в безопасности от него.

...