Как PreparedStatement избежать или предотвратить SQL-инъекции?
Я знаю, что PreparedStatements избежать/предотвратить SQL-инъекции. Как он это делает? Будет ли конечный запрос формы, построенный с использованием PreparedStatements, строкой или иным образом?
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 получает запрос, он должен пройти через этапы ниже,
фаза разбора и нормализации: На этом этапе запрос проверяется на синтаксис и семантику. Он проверяет ли ссылки таблица и столбцы, используемые в запросе или нет. Она также имеет много других задач, но давайте не будем вдаваться в подробности.
Компиляции Фаза: На этом этапе ключевые слова, используемые в запросе, такие как select, from, где etc преобразуются в формат понятно по машине. Это этап, на котором интерпретируется запрос и решается соответствующее действие. У него также есть много других задач, но давайте не будем заходить деталь.
План Оптимизации Запросов: На этом этапе создается дерево решений для поиска способов выполнения запроса. Он определяет количество способов выполнения запроса и стоимость, связанную с каждым из них выполнения запроса. Он выбирает наилучший план выполнения запроса.
кэширование: Лучший план, выбранный в плане оптимизации запросов, хранится в кэше, так что всякий раз, когда следующий когда приходит тот же запрос, он не должен проходить через фазу 1, фазу 2 и фазу 3 снова. Когда в следующий раз запрос придет, он будет проверен непосредственно в кэше и подобран оттуда во исполнение.
Выполнение Работ: На этом этапе выполняется предоставленный запрос, и данные возвращаются пользователю как
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, содержащую исполняемую команду: использование подготовленного заявления не позволит этого.
Он добавляет metacharacter (a.к. a. автоматическое преобразование) к этому.
это делает его более безопасным.
Как поясняется в этот пост на PreparedStatement
один не поможет вам, если вы все еще объединяете строки.
например, один злоумышленник-изгоев все еще может сделать следующее:
- вызовите функцию сна, чтобы все ваши подключения к базе данных были заняты, поэтому ваше приложение недоступно
- извлечение конфиденциальных данных из БД
- обход пользователя проверка подлинности
не только SQL, но даже JPQL или HQL могут быть скомпрометированы, если вы не используете параметры привязки.
в нижней строке вы никогда не должны использовать конкатенацию строк при создании операторов SQL. Используйте выделенный API для этой цели:
SQL injection: когда пользователь имеет возможность ввести что-то, что может быть частью инструкции sql
например:
String query = " вставить в значения студентов ('"+user +"‘)"
при вводе пользователем "Robert’); -" в качестве ввода он вызывает SQL-инъекцию
Как подготовленное заявление этому мешает?
String query = "вставить в значения студентов (‘" + ": name" + "‘)"
параметры.addValue("наименование", пользователь);
=> когда пользователь снова вводит " Robert’); DROP TABLE students;–", входная строка предварительно скомпилирована на драйвере как литеральные значения, и я думаю, что она может быть отлита как:
CAST ('Robert’); падение таблицы студентов; – ‘ 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 ().