Как PreparedStatement избежать или предотвратить SQL-инъекции?



Я знаю, что PreparedStatements избежать/предотвратить SQL-инъекции. Как он это делает? Будет ли окончательный запрос формы, построенный с использованием PreparedStatements, строкой или иначе?

279   9  

9 ответов:

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

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

рассмотрим два способа сделать то же самое:

PreparedStatement stmt = conn.createStatement("INSERT INTO students VALUES('" + user + "')");
stmt.execute();

или

PreparedStatement stmt = conn.prepareStatement("INSERT INTO student VALUES(?)");
stmt.setString(1, user);
stmt.execute();

если "пользователь" пришел из пользовательского ввода и ввода пользователь

Robert'); DROP TABLE students; --

тогда в первую очередь, вы бы прогорели. Во-вторых, вы будете в безопасности, и маленькие столы Бобби будут зарегистрированы для вашей школы.

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

1. Этап Компиляции. 2. выполнение работ.

всякий раз, когда SQL server engine получает запрос, он должен пройти через следующие фазы,

Query Execution Phases

  1. фаза разбора и нормализации: На этом этапе запрос проверяется на синтаксис и семантику. Он проверяет ли ссылки таблицы и столбцы, используемые в запросе или нет. У него также есть много других задач, но давайте не будем вдаваться в детали.

  2. Компиляции Фаза: На этом этапе ключевые слова, используемые в запросе, такие как select, from, where etc, преобразуются в формат понятно по машине. Это фаза, на которой интерпретируется запрос и решается соответствующее действие. У него также есть много других задач, но давайте не будем входить деталь.

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

  4. кэширование: Лучший план, выбранный в плане оптимизации запросов, хранится в кэше, так что всякий раз, когда следующий время же запрос приходит, он не должен проходить через фазу 1, фазу 2 и фазу 3 снова. Когда в следующий раз запрос придет, он будет проверен непосредственно в кэше и подобран оттуда во исполнение.

  5. Выполнение Работ: На этом этапе выполняется предоставленный запрос и данные возвращаются пользователю как

SQL, используемый в PreparedStatement, предварительно компилируется на драйвере. С этого момента параметры отправляются в драйвер как литеральные значения, а не исполняемые части SQL; таким образом, SQL не может быть введен с помощью параметра. Другим полезным побочным эффектом PreparedStatements (precompilation + sending only parameters) является повышение производительности при многократном запуске оператора даже с разными значениями параметров (при условии, что драйвер поддерживает PreparedStatements) поскольку драйвер не должен выполнять синтаксический анализ и компиляцию SQL каждый раз, когда параметры изменяются.

Я Угадай это будет строка. Но входные параметры будут отправлены в базу данных и соответствующие приведения/преобразования будут применены до создания фактического оператора SQL.

чтобы дать вам пример, он может попробовать и посмотреть, работает ли приведение/преобразование.
Если он работает, он может создать из него окончательное утверждение.

   SELECT * From MyTable WHERE param = CAST('10; DROP TABLE Other' AS varchar(30))

попробуйте пример с оператором SQL, принимающим числовой параметр.
Теперь попробуйте передать строковую переменную (с числовым содержимым, которое приемлемо в качестве числового параметра). Это вызывает ошибки?

теперь попробуйте передать строковую переменную (с содержимым, которое не является приемлемым в качестве числового параметра). Видишь, что происходит?

подготовленное заявление является более безопасным. Он преобразует параметр в указанный тип.

stmt.setString(1, user); преобразовать user параметр для строки.

предположим, что параметр содержит строку SQL, содержащую исполняемую команду: использование подготовленного заявления не позволит этого.

Он добавляет метасимвол (он же автоматическое преобразование) к этому.

это делает его более безопасным.

Как поясняется в этот пост на PreparedStatement в одиночку не поможет вам, если вы все еще конкатенации строк.

например, один злоумышленник-мошенник все еще может сделать следующее:

не только SQL, но даже JPQL или HQL могут быть скомпрометированы, если вы не используете параметры привязки.

итог, вы никогда не должны использовать конкатенацию строк при создании инструкций SQL. Используйте выделенный API для этой цели:

SQL инъекции: когда пользователь имеет возможность ввести что-то, что может быть частью инструкции sql

например:

String query = " вставить в значения студентов ('"+user +"‘)"

при вводе пользователем "Robert'); DROP TABLE students; - " в качестве ввода он вызывает SQL-инъекцию

Как подготовленное заявление этому мешает?

String query = "вставить в значения студентов (‘" + ": name" + "' )"

параметры.addValue("наименование", пользователь);

=> когда пользователь вводит снова "Robert'); DROP TABLE students;–", входная строка предварительно скомпилирована на драйвере как литеральные значения, и я думаю, что она может быть отлита как:

CAST ('Robert’); DROP TABLE students; – ‘ AS varchar(30))

таким образом, в конце строка будет буквально вставлена в качестве имени стол.

http://blog.linguiming.com/index.php/2018/01/10/why-prepared-statement-avoids-sql-injection/

PreparedStatement:

1) предварительная компиляция и кэширование на стороне БД инструкции SQL приводит к общему ускорению выполнения и возможности повторного использования одной и той же инструкции SQL в пакетах.

2) автоматическое предотвращение атак SQL-инъекций путем встроенного экранирования кавычек и других специальных символов. Обратите внимание, что для этого необходимо использовать любой из методов PreparedStatement setXxx() для установки значения.

    Ничего не найдено.

Добавить ответ:
Отменить.