Существует альтернативное решение с анимацией css для скрытого скрытого:
.dropdown{
position: relative;
width: 100%;
-webkit-animation-name: animatetop;
-webkit-animation-duration: 0.4s;
animation-name: animatetop;
animation-duration: 0.4s
}
/* Add Animation */
@-webkit-keyframes animatetop {
from {top:-300px; opacity:0}
to {top:0; opacity:1}
}
@keyframes animatetop {
from {top:-300px; opacity:0}
to {top:0; opacity:1}
}
Ссылки, которые я опубликовал в моих комментариях к вопросу, очень хорошо объясняют проблему. Я обобщил свои чувства по поводу того, почему проблема сохраняется, ниже:
php mysql query
, первая страница появится на странице mysql_query
, на которой есть пример, который отображает интерполяцию экранированного пользовательского ввода в запрос. Нет никакого упоминания (по крайней мере, не того, что я могу видеть) вместо использования подготовленных инструкций. Как говорили другие, существует так много учебных пособий, которые используют интерполяцию параметров, что не удивительно, как часто она все еще используется. Хороший вопрос. Ответ более стохастичен, чем детерминированный, и я попытаюсь объяснить свое мнение, используя небольшой пример.
В сети много ссылок, которые предлагают нам использовать параметры в наших запросах или использовать хранимую процедуру с параметрами чтобы избежать SQL Injection (SQLi). Я покажу вам, что хранимые процедуры (например) не являются волшебной палочкой против SQLi. Ответственность по-прежнему остается у программиста.
Рассмотрим следующую хранимую процедуру SQL Server, которая выведет строку пользователя из таблицы «Пользователи»:
create procedure getUser
@name varchar(20)
,@pass varchar(20)
as
declare @sql as nvarchar(512)
set @sql = 'select usrID, usrUName, usrFullName, usrRoleID '+
'from Users '+
'where usrUName = '''+@name+''' and usrPass = '''+@pass+''''
execute(@sql)
Вы можете получить результаты путем передачи в качестве параметров имени пользователя и пароля. Предположим, что пароль находится в свободном тексте (просто для простоты этого примера) нормальный вызов:
DECLARE @RC int
DECLARE @name varchar(20)
DECLARE @pass varchar(20)
EXECUTE @RC = [dbo].[getUser]
@name = 'admin'
,@pass = '!@Th1siSTheP@ssw0rd!!'
GO
Но здесь у нас плохой метод программирования, используемый программистом внутри хранимой процедуры, поэтому злоумышленник может выполнить следующее:
DECLARE @RC int
DECLARE @name varchar(20)
DECLARE @pass varchar(20)
EXECUTE @RC = [TestDB].[dbo].[getUser]
@name = 'admin'
,@pass = 'any'' OR 1=1 --'
GO
Вышеуказанные параметры будут переданы в качестве аргументов хранимой процедуры, а команда SQL, которая в конечном итоге будет выполнена, будет:
select usrID, usrUName, usrFullName, usrRoleID
from Users
where usrUName = 'admin' and usrPass = 'any' OR 1=1 --'
. , который получит все строки от пользователей
. Проблема в том, что даже мы следуем принципу «Создаем хранимую процедуру и передаем поля для поиска в качестве параметров», SQLi все еще выполняется. Это связано с тем, что мы просто копируем нашу плохую практику программирования внутри хранимой процедуры. Решение этой проблемы состоит в том, чтобы переписать нашу Хранимую процедуру следующим образом:
alter procedure getUser
@name varchar(20)
,@pass varchar(20)
as
select usrID, usrUName, usrFullName, usrRoleID
from Users
where usrUName = @name and usrPass = @pass
То, что я пытаюсь сказать, заключается в том, что разработчики должны сначала узнать, что такое SQLi-атака, и как ее можно выполнить, а затем соответственно защищать их код. Слепо следовать «лучшим практикам» - это не всегда безопасный способ ... и, возможно, именно поэтому у нас так много «лучших практик» - не удается!
Да, использование подготовленных операторов останавливает все инъекции SQL, по крайней мере теоретически. На практике параметризованные операторы могут быть не реальными подготовленными операциями, например. PDO
в PHP имитирует их по умолчанию, поэтому открыт для атаки кромки кромки .
Если вы используете реальные подготовленные заявления, все в порядке. Ну, по крайней мере, до тех пор, пока вы не объединяете небезопасный SQL в свой запрос, как реакцию на невозможность подготовить имена таблиц, например.
Если да, почему еще так много успешных SQL-инъекции? Просто потому, что некоторые разработчики слишком глупы, чтобы использовать параметризованные утверждения?
blockquote>Да, здесь основное внимание уделяется образованию и устаревшим кодам. К сожалению, многие учебники используют экранирование, и, к сожалению, они не могут быть легко удалены из Интернета.
SQL-инъекция - это подмножество большей проблемы ввода кода, где данные и код предоставляются по одному каналу, а данные ошибочны для кода. Параметрированные запросы предотвращают это, формируя запрос с использованием контекста о том, что такое данные и что такое код.
В некоторых конкретных случаях этого недостаточно. Во многих СУБД можно динамически выполнять SQL с хранимыми процедурами, представляя ошибку SQL-инъекции на уровне СУБД. Вызов такой хранимой процедуры с использованием параметризованных запросов не будет препятствовать использованию SQL-инъекции в процедуре. Другой пример можно увидеть в в этом сообщении в блоге .
Чаще всего разработчики неправильно используют эту функцию. Обычно код выглядит примерно так, когда выполняется правильно:
db.parameterize_query("select foo from bar where baz = '?'", user_input)
Некоторые разработчики объединяют строки вместе, а затем используют параметризованный запрос, который фактически не делает вышеупомянутое разграничение данных / кода, обеспечивающее безопасность которые мы ищем:
db.parameterize_query("select foo from bar where baz = '" + user_input + "'")
Правильное использование параметризованных запросов обеспечивает очень прочную, но непроницаемую защиту от атак SQL-инъекций.
Я избегаю абсолютов в программировании; всегда есть исключение. Я настоятельно рекомендую хранимые процедуры и объекты команд. Большая часть моей базы с SQL Server, но я играю с MySql время от времени. Существует множество преимуществ хранимых процедур, включая кэшированные планы запросов; да, это может быть достигнуто с помощью параметров и встроенного SQL, но это открывает больше возможностей для инъекционных атак и не помогает с разделением проблем. Для меня также намного проще защитить базу данных, поскольку мои приложения обычно имеют только разрешение на выполнение указанных хранимых процедур. Без прямого доступа к таблицам и представлениям гораздо сложнее вводить что-либо. Если пользователь приложений скомпрометирован, у него есть только разрешение на выполнение того, что было предварительно определено.
Мои два цента.
Поскольку большинство кодеков не написано с учетом безопасности и управления, учитывая выбор между добавлением функций (особенно что-то видимое, которое можно продать) и безопасностью / стабильностью / надежностью (что гораздо труднее продать), они будут почти неизменно выбирают первое. Безопасность является лишь проблемой, когда она становится проблемой.
Чтобы защитить приложение от SQL-инъекции, выполните следующие шаги:
Шаг 1. Ограничьте ввод. Шаг 2. Используйте параметры с хранимыми процедурами. Шаг 3. Используйте параметры с динамическим SQL.
, даже если подготовленные утверждения правильно используются во всем собственном коде веб-приложения, ошибки SQL-инъекции могут все еще существовать, если компоненты кода базы данных строят запросы с пользовательского ввода небезопасным образом. Ниже приведен пример хранимой процедуры, которая уязвима для SQL-инъекции в параметре @name:
CREATE PROCEDURE show_current_orders
(@name varchar(400) = NULL)
AS
DECLARE @sql nvarchar(4000)
SELECT @sql = ‘SELECT id_num, searchstring FROM searchorders WHERE ‘ +
‘searchstring = ‘’’ + @name + ‘’’’;
EXEC (@sql)
GO
Даже если приложение передает сохраненное пользователю значение имени в хранимую процедуру безопасным образом , сама процедура объединяет это непосредственно в динамический запрос и поэтому уязвима.
Когда в статьях рассказывается о параметризованных запросах, останавливающих атаки SQL, они на самом деле не объясняют, почему это часто бывает так: «Это так, поэтому не спрашивайте, почему» - возможно, потому что они сами не знают. Верным признаком плохого педагога является тот, который не может признать, что он ничего не знает. Но я отвлекся. Когда я говорю, я понял, что совершенно понятно, что меня путают просто. Представьте себе динамический SQL-запрос
sqlQuery='SELECT * FROM custTable WHERE User=' + Username + ' AND Pass=' + password
, поэтому простая инсталляция sql должна была просто ввести имя пользователя в качестве «OR 1 = 1». Это действительно сделало бы запрос sql:
sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS=' + password
В этом заявлении указывается, что все клиенты, где они являются, являются пустыми ('') или 1 = 1, что является логическим, приравнивая true. Затем он использует - чтобы прокомментировать остальную часть запроса. Таким образом, это будет просто распечатывать всю таблицу клиентов или делать с ней все, что вы захотите, если он войдет в систему, он войдет в систему с привилегиями первого пользователя, которые часто могут быть администратором.
Теперь параметризованные запросы делайте это по-другому, с кодом типа:
sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?'
parameters.add("User", username)
parameters.add("Pass", password)
, где имя пользователя и пароль являются переменными, указывающими на связанное введенное имя пользователя и пароль
. Теперь вы можете думать, что это ничего не меняет. Конечно, вы все равно могли бы просто ввести в поле имени пользователя что-то вроде Nobody OR 1 = 1 '-, эффективно выполнив запрос:
sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND Pass=?'
И это похоже на действительный аргумент. Но вы ошибаетесь.
Способ работы с параметризованными запросами заключается в том, что sqlQuery отправляется как запрос, и база данных точно знает, что будет делать этот запрос, и только после этого он будет вставлять имя пользователя и пароли просто как ценности. Это означает, что они не могут выполнить запрос, потому что база данных уже знает, что будет делать запрос. Таким образом, в этом случае он будет искать имя пользователя «Nobody OR 1 = 1 '-» и пустой пароль, который должен выглядеть ложным.
Это не полное решение, хотя и вход валидация все равно потребуется, так как это не повлияет на другие проблемы, такие как атаки XSS, поскольку вы все равно можете поместить javascript в базу данных. Затем, если это зачитано на странице, оно будет отображать его как обычный javascript, в зависимости от какой-либо проверки валидации. Так что лучше всего по-прежнему использовать проверку ввода, но используя параметризованные запросы или хранимые процедуры, чтобы остановить любые атаки SQL.
Я бы не сказал «тупой».
Я думаю, что это проблемы. Большинство учебников по SQL, книги, все, что объясняет SQL со встроенными значениями, вообще не упоминают параметры привязки. Люди, изучающие эти учебные пособия, не имеют возможности изучить его правильно.
Сначала мой ответ на ваш первый вопрос: Да, насколько я знаю, с помощью параметризованных запросов SQL-инъекции больше не будут возможны. Что касается ваших следующих вопросов, я не уверен и могу только рассказать вам о причинах:
Я думаю, что проще «просто» написать строку запроса SQL, объединив некоторые разные части (возможно, даже зависимые на некоторых логических проверках) вместе со значениями, которые нужно вставить. Он просто создает запрос и выполняет его. Другим преимуществом является то, что вы можете печатать (эхо, вывод или что-то еще) строку запроса sql, а затем использовать эту строку для ручного запроса к движку базы данных.
При работе с подготовленными операторами вы всегда имеете как минимум еще один шаг: вам нужно построить свой запрос (включая параметры, конечно). Вы должны подготовить запрос на сервере. Вы должны привязать параметры к фактическим значениям, которые вы хотите использовать для своего запроса. Вы должны выполнить запрос .
Это немного больше работает (и не так просто программировать), особенно для некоторых «быстрых и грязных» заданий, которые часто оказываются очень долговечными ...
С наилучшими пожеланиями ,
Коробка
Может ли параметризованный оператор остановить всю инъекцию SQL?
blockquote>Да, если ваш драйвер базы данных предлагает заполнитель для каждого возможного литерала SQL. У большинства подготовленных драйверов инструкций нет. Скажем, вы никогда не найдете местозаполнитель для имени поля или массива значений. Это заставит разработчика откидываться назад на посылку запроса вручную, используя конкатенацию и ручное форматирование. С предсказанным результатом.
Вот почему я сделал свою Mysql-оболочку для PHP, которая поддерживает большинство литералов, которые могут быть добавлены в запрос динамически, включая массивы и идентификаторы.
Если да, почему еще так много успешных инъекций SQL? Просто потому, что некоторые разработчики слишком глупы, чтобы использовать параметризованные утверждения?
blockquote>Как вы можете видеть, на самом деле просто невозможно, чтобы все задавали ваши запросы, даже если вы «Не тупой.