SQL инъекции для самых маленьких Часть 2. UNION запросы / Хабр
Это вторая по счету статься из цикла про SQL инъекции. В данном статье мы с вами рассмотрим особенности SQL инъекций при использовании команды UNION.
Так для начала разберемся, что делает команда UNION.
Ключевое слово UNION позволяет выполнить один или несколько дополнительных запросов SELECT и добавить их результаты к исходному запросу. Например:
SELECT a, b FROM table1 UNION SELECT c, d FROM
table2
Этот SQL-запрос вернет один набор результатов с двумя столбцами, содержащий значения из столбцов a и b в таблице 1 и столбцов c и d в таблице 2. Важно помнить, что:
1. UNION должен возвращать одинаковое количество столбцов
2. Типы данных в каждом столбце должны быть совместимы между отдельными запросами.
Чтобы осуществить атаку SQL-инъекции UNION, необходимо убедиться, что ваша атака отвечает этим двум требованиям. Обычно для этого необходимо выяснить сколько столбцов возвращается из исходного запроса.
При выполнении атаки UNION в SQL-инъекции существует два эффективных метода определения количества столбцов, возвращаемых из исходного запроса.
Первый метод заключается в инъекции серии предложений ORDER BY и увеличении индекса указанного столбца до тех пор, пока не возникнет ошибка. Например, если предположить, что точкой инъекции является строка в кавычках в пункте WHERE исходного запроса, то можно отправить:
' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3--
и т.д.
Эта серия полезных нагрузок изменяет исходный запрос, чтобы упорядочить результаты по различным столбцам в наборе результатов. Столбец в предложении ORDER BY может быть указан по его индексу, поэтому вам не нужно знать имена столбцов. Если указанный индекс столбца превышает количество фактических столбцов в наборе результатов, база данных выдает ошибку, например:
Позиция ORDER BY с номером 3 находится вне диапазона количества элементов в списке выбора, так как уже ничего не возвращает. Это потолок.
Приложение может действительно вернуть ошибку базы данных в своем HTTP-ответе, или оно может вернуть общую ошибку, или просто не выдать никаких результатов. Если вы сможете обнаружить разницу в ответе приложения, вы сможете определить, сколько столбцов возвращается из запроса.
Второй метод заключается в передаче серии запросов UNION SELECT, в которых указывается разное количество нулевых значений:
‘ UNION SELECT NULL—
‘ UNION SELECT NULL,NULL—
‘ UNION SELECT NULL,NULL,NULL—
и т.д.
Если количество нулевых значений не совпадает с количеством столбцов, база данных возвращает ошибку.
Опять же, приложение может действительно вернуть это сообщение об ошибке, а может просто вернуть общую ошибку или отсутствие результатов. Когда количество нулей совпадает с количеством столбцов, база данных возвращает дополнительную строку в наборе результатов, содержащую нулевые значения в каждом столбце. Влияние на результирующий ответ HTTP зависит от кода приложения. Если вам повезет, вы увидите в ответе какое-то дополнительное содержимое, например, дополнительную строку в HTML-таблице. В противном случае нулевые значения могут вызвать другую ошибку, например, NullPointerException. В худшем случае ответ может быть неотличим от того, который вызван неправильным количеством нулей, что делает этот метод определения количества столбцов неэффективным.
Причина использования NULL в качестве значений, возвращаемых из инжектированного запроса SELECT, заключается в том, что типы данных в каждом столбце должны быть совместимы между исходным и инжектированным запросами. Поскольку NULL конвертируется в каждый часто используемый тип данных, использование NULL максимизирует вероятность того, что полезная нагрузка будет успешной, если счетчик столбцов правильный.
В Oracle каждый запрос SELECT должен использовать ключевое слово FROM и указывать допустимую таблицу. В Oracle существует встроенная таблица под названием dual, которая может быть использована для этой цели. Таким образом, инжектированные запросы в Oracle должны выглядеть следующим образом:
' UNION SELECT NULL FROM DUAL-.
Описанные полезные нагрузки используют последовательность комментариев с двойным тире —, чтобы закомментировать остаток исходного запроса после точки инъекции. В MySQL за последовательностью двойного тире должен следовать пробел. В качестве альтернативы для идентификации комментария можно использовать хэш-символ #.
Поиск столбцов с полезным типом данных в атаке UNION при SQL-инъекции
Причина выполнения атаки UNION при SQL-инъекции заключается в том, чтобы иметь возможность получить результаты введенного запроса. Как правило, интересные данные, которые вы хотите получить, будут в строковой форме, поэтому вам нужно найти один или несколько столбцов в результатах исходного запроса, тип данных которых является или совместим со строковыми данными.
Определив количество необходимых столбцов, вы можете проверить каждый столбец на возможность хранения строковых данных, выполнив серию запросов UNION SELECT, которые помещают строковое значение в каждый столбец по очереди. Например, если запрос возвращает четыре столбца, вы должны отправить:
' UNION SELECT 'a',NULL,NULL,NULL--.
' UNION SELECT NULL,'a',NULL,NULL--
' UNION SELECT NULL,NULL,'a',NULL--
' UNION SELECT NULL,NULL,NULL,'a'--.
Если тип данных столбца не совместим со строковыми данными, инжектированный запрос вызовет ошибку базы данных, например:
При преобразовании значения varchar ‘a’ в тип данных int произошел сбой преобразования.
Если ошибка не возникает, а ответ приложения содержит некоторое дополнительное содержимое, включая введенное строковое значение, значит, соответствующий столбец подходит для получения строковых данных.
Использование SQL-инъекции UNION для получения полезных данных
Предположим, что:
1. Исходный запрос возвращает два столбца, оба из которых могут содержать строковые данные.
2. Точкой введения является строка в кавычках в предложении WHERE.
3. База данных содержит таблицу users с колонками username и password.
В этой ситуации вы можете получить содержимое таблицы users, выполнив ввод:
' UNION SELECT username, password FROM users--
Конечно, решающей информацией, необходимой для выполнения этой атаки, является то, что существует таблица users с двумя столбцами username и password. Без этой информации вам пришлось бы пытаться угадать имена таблиц и столбцов. На самом деле, все современные базы данных предоставляют возможность исследовать структуру базы данных, чтобы определить, какие таблицы и столбцы она содержит.
Извлечение нескольких значений в одном столбце
В предыдущем примере предположим, что запрос возвращает только один столбец.
Вы можете легко получить несколько значений вместе в этом единственном столбце, объединив их вместе, в идеале включив подходящий разделитель, который позволит вам различать объединенные значения. Например, в Oracle вы можете ввести:
' UNION SELECT username || '~' || password FROM users--
В этом случае используется последовательность двойного разделителя ||, который является оператором конкатенации строк в Oracle. Введенный запрос объединяет значения полей имя пользователя и пароль, разделенные символом ~.
Результаты запроса позволят вам прочитать все имена пользователей и пароли, например:
administrator~admin
user1~pass1
user2~pass2
Обратите внимание, что разные базы данных используют разный синтаксис для выполнения конкатенации строк.
Это была 2 часть из цикла статей про SQL-инъекции. Совсем скоро выйдет часть 3.
Объединение UNION и UNION ALL в SQL – описание и примеры | Info-Comp.ru
Пришло время поговорить об объединении данных по средствам конструкции union и union all, так как это иногда бывает очень полезно, и без использования такой конструкции бывает порой не обойтись. Примеры будем писать в СУБД MSSQL 2008, используя язык SQL.
И начать хотелось бы с того, что мы с Вами уже рассматривали много примеров написания запросов на SQL, например, оператор select языка SQL, или использование строковых функций SQL, также рассматривали программирование как на plpgsql так и на transact-sql, например, Как написать функцию на PL/pgSQL и Transact-sql – Табличные функции и временные таблицы соответственно.
Я не просто так указал вышеперечисленные статьи, а указал я их, потому, что для более лучшего понимания и усвоения сегодняшнего урока, необходимо начальные знания (это сайт для начинающих программистов), которые как раз Вы можете получить из вышеупомянутого материала.
И так приступим. И для начала давайте рассмотрим, что же это за операторы union и union all.
Заметка! Профессиональный видеокурс по T-SQL для начинающих.
Содержание
- Что такое UNION и UNION ALL в SQL?
- Необходимые условия для операторов union и union all
- Примеры использования union и union all
Что такое UNION и UNION ALL в SQL?
- UNION – это оператор SQL для объединения результирующего набора данных нескольких запросов, и данный оператор выводит только уникальные строки в запросах, т. е. например, Вы объединяете два запроса и в каждом из которых есть одинаковые данные, другими словами полностью идентичные, и оператор union объединит их в одну строку для того чтобы не было дублей;
- UNION ALL – это оператор SQL для объединения результирующего набора данных нескольких запросов, а вот данный оператор, выведет уже абсолютно все строки, даже дубли.
Необходимые условия для операторов union и union all
- Набор полей должен быть одинаковый во всех запросах, т.е. количество полей в каждом запросе, который будет объединяться по средствам конструкции union или union all, должно быть одинаковое;
- Типы данных полей также должны совпадать в каждом запросе, т.е. например, если Вы захотите написать один запрос, в котором будет тип данных int а во втором запросе тип данных varchar то у Вас запрос не выполнится а окно запроса выведет ошибку;
- В случае сортировки оператор order by можно указать только после последнего запроса.
Теперь давайте поговорим о том, в каких случаях нам может понадобиться использование этих операторов. Ну, например, у Вас есть несколько баз со схожей структурой, каждая из которых создана, например, для какого-нибудь филиала, а Вам необходимо объединить эти данные для предоставления отчетности по всем филиалам руководству и самое простое как это можно сделать, это написать запросы на SQL, каждый из которых будет обращаться к разным базам, и через конструкцию union или union all объединить их. Также иногда бывает необходимо объединить данные в одной базе таким образом, что обычными объединениями это не реализовать и приходится использовать union. Почему я говорю «приходится» да потому что данная конструкция значительно увеличивает время выполнения запроса, если например данных очень много, и злоупотреблять ею не нужно.
Хватит теории, переходим к практике.
Примечание! Как уже говорилось, запросы будем писать в Management Studio для SQL Server 2008
Примеры использования union и union all
Для начала создадим две простых таблицы test_table и test_table_2
CREATE TABLE [test_table]( [id] [bigint] IDENTITY(1,1) NOT NULL, [number] [numeric](18, 0) NULL, [text] [varchar](50) NULL, CONSTRAINT [PK_test_table] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO SET ANSI_PADDING OFF GO --и вторая таблица CREATE TABLE [test_table_2]( [id] [bigint] IDENTITY(1,1) NOT NULL, [number] [numeric](18, 0) NULL, [text] [varchar](50) NULL, CONSTRAINT [PK_test_table_2] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO SET ANSI_PADDING OFF GO
Они одинаковые для примера, только разные названия. Я заполнил их вот такими данными:
Теперь давайте напишем запрос, который объединит результирующие данные в одни, например через union. Синтаксис очень прост:
Запрос 1 union Запрос 2 union Запрос 3 и т.д.
Вот запрос:
select number, text from test_table union select number, text from test_table_2
Как Вы видите, вывелось всего 5 строк, так как у нас первая строка в первом запросе и первая строка во втором запросе одинаковые, поэтому они объединились.
Теперь давайте объединим через union all
Вот запрос:
select number, text from test_table union all select number, text from test_table_2
Здесь уже вывелись все строки, так как мы указали union all.
А теперь давайте рассмотрим, какие могут быть ошибки даже в этом простом запросе. Например, мы перепутали последовательность полей:
Или мы в первом запросе указали дополнительное поле, а во втором этого не сделали.
Также, например, при использовании order by:
Здесь мы указали сортировку в каждом запросе, а нужно было только в последнем, например:
select number, text from test_table union all select number, text from test_table_2 order by number
И напоследок, хотел рассказать об одной хитрости, которую можно использовать тогда когда, например, все-таки необходимо вывести в одном запросе какое-то поле, а в других его нет или просто оно не нужно, для этого можете написать вот такой запрос:
select id ,number, text from test_table union all select '', number, text from test_table_2
т.е. как Вы видите просто там, где должно быть поле ставить пусто и запрос отлично отработает, например:
И еще один небольшой совет, так как запросы при объединении через union довольно обширные, то лучше на их основе создать представление (Views), в случае если данный запрос Вам требуется постоянно, и уже к этому представлению обращаться каждый раз, когда требуется, а зачем нужны представления мы с Вами уже рассматривали вот здесь – Что такое представления и зачем они нужны.
Наверное, все, что я хотел рассказать о конструкции union и union all языка SQL я рассказал, если есть вопросы по использованию этих операторов, задавайте их в комментариях. Удачи!
Заметка! Для комплексного изучения языка T-SQL рекомендую посмотреть мои видеокурсы по T-SQL, в которых используется последовательная методика обучения и рассматриваются все конструкции языка SQL и T-SQL.
SQL-инъекций UNION атак | Академия веб-безопасности
Когда приложение уязвимо для SQL-инъекций и результаты запроса возвращаются в ответах приложения, можно использовать ключевое слово
для извлечения данных из других таблиц в базе данных. Это приводит к атаке UNION с внедрением SQL.
Ключевое слово UNION
позволяет выполнить один или несколько дополнительных запросов SELECT
и добавить результаты к исходному запросу. Например:
SELECT a, b FROM table1 UNION SELECT c, d FROM table2
Этот запрос SQL вернет один набор результатов с двумя столбцами, содержащими значения из столбцов a
и b
в table1
и столбцов c
d
в table2
. Чтобы запрос UNION
работал, необходимо выполнить два ключевых требования:
- Отдельные запросы должны возвращать одинаковое количество столбцов.
- Типы данных в каждом столбце должны быть совместимы между отдельными запросами.
Чтобы выполнить атаку UNION с внедрением SQL, вам необходимо убедиться, что ваша атака соответствует этим двум требованиям. Обычно это включает в себя выяснение:
- Сколько столбцов возвращается из исходного запроса?
- Какие столбцы, возвращенные исходным запросом, имеют подходящий тип данных для хранения результатов введенного запроса?
Определение количества столбцов, необходимых для SQL-инъекции UNION-атаки
При выполнении атаки UNION с внедрением SQL существует два эффективных метода определения количества столбцов, возвращаемых исходным запросом.
Первый метод включает в себя вставку серии из предложений ORDER BY
и увеличение указанного индекса столбца до тех пор, пока не произойдет ошибка. Например, предположим, что точка инъекции — это строка в кавычках в пределах
исходного запроса, вы должны отправить:
' ПОРЯДОК ПО 1--
ЗАКАЗАТЬ ПО 2--
ЗАКАЗАТЬ ПО 3--
и т.д.
Эта серия полезных данных изменяет исходный запрос, чтобы упорядочить результаты по разным столбцам в результирующем наборе. Столбец в предложении ORDER BY
можно указать по его индексу, поэтому вам не нужно знать имена каких-либо столбцов. Когда указанный индекс столбца превышает количество фактических столбцов в результирующем наборе, база данных возвращает ошибку, например:
Позиция ORDER BY номер 3 выходит за пределы количества элементов в списке выбора.
Приложение может фактически вернуть ошибку базы данных в своем HTTP-ответе, или общую ошибку, или просто не вернуть никаких результатов. Если вы можете обнаружить некоторую разницу в ответе приложения, вы можете сделать вывод о том, сколько столбцов возвращается из запроса.
Второй способ предполагает подачу серии из UNION SELECT
полезной нагрузки, указывающей другое количество нулевых значений:
'ОБЪЕДИНЕНИЕ ВЫБЕРИТЕ NULL--
' ОБЪЕДИНЕНИЕ SELECT NULL, NULL--
' ОБЪЕДИНЕНИЕ SELECT NULL, NULL, NULL--
и т.д.
Если количество нулей не соответствует количеству столбцов, база данных возвращает ошибку, например:
Все запросы, объединенные с помощью оператора UNION, INTERSECT или EXCEPT, должны иметь одинаковое количество выражений в своих целевых списках.
Опять же, приложение может на самом деле вернуть это сообщение об ошибке или может просто вернуть общую ошибку или никаких результатов. Когда количество пустых значений совпадает с количеством столбцов, база данных возвращает дополнительную строку в результирующем наборе, содержащую нулевые значения в каждом столбце. Влияние на результирующий HTTP-ответ зависит от кода приложения. Если вам повезет, вы увидите дополнительный контент в ответе, например дополнительную строку в таблице HTML. В противном случае нулевые значения могут вызвать другую ошибку, например NullPointerException
. В худшем случае ответ может быть неотличим от ответа, вызванного неправильным количеством нулей, что делает этот метод определения количества столбцов неэффективным.
ПРАКТИК SQL-инъекция UNION-атака, определяющая количество столбцов, возвращаемых запросом
Note
Дополнительные сведения о синтаксисе, специфичном для базы данных, см. в памятке по SQL-инъекциям.
Поиск столбцов с полезным типом данных в атаке UNION с внедрением SQL
Причина выполнения атаки UNION с внедрением SQL-кода заключается в том, чтобы иметь возможность получить результаты из введенного запроса. Как правило, интересные данные, которые вы хотите получить, будут в форме строки, поэтому вам нужно найти один или несколько столбцов в исходных результатах запроса, тип данных которых является или совместим со строковыми данными.
Уже определив количество необходимых столбцов, вы можете проверить каждый столбец, чтобы проверить, может ли он содержать строковые данные, отправив серию из UNION SELECT
полезные данные, которые помещают строковое значение в каждый столбец по очереди. Например, если запрос возвращает четыре столбца, вы должны отправить:
' ОБЪЕДИНЕНИЕ ВЫБЕРИТЕ 'a', NULL, NULL, NULL--
' UNION SELECT NULL,'a',NULL,NULL--
' UNION SELECT NULL, NULL, 'a', NULL--
' UNION SELECT NULL,NULL,NULL,'a'--
Если тип данных столбца несовместим со строковыми данными, введенный запрос вызовет ошибку базы данных, например:
Ошибка преобразования при преобразовании значения varchar 'a' в тип данных int.
Если ошибка не возникает, а ответ приложения содержит некоторое дополнительное содержимое, включая введенное строковое значение, то соответствующий столбец подходит для получения строковых данных.
ЛАБОРАТОРИЯПРАКТИК Атака UNION с внедрением SQL, поиск столбца, содержащего текст
Использование атаки UNION с внедрением SQL для извлечения интересных данных
Когда вы определили количество столбцов, возвращаемых исходным запросом, и нашли, какие столбцы могут содержать строковые данные, вы можете получить интересные данные.
Предположим, что:
- Исходный запрос возвращает два столбца, оба из которых могут содержать строковые данные.
- Точка внедрения — это строка в кавычках в предложении
WHERE
. - База данных содержит таблицу с именем
пользователей
со столбцамиимя пользователя
ипароль
.
В этой ситуации вы можете получить содержимое таблицы пользователей
, отправив ввод:
' ОБЪЕДИНЕНИЕ ВЫБЕРИТЕ имя пользователя, пароль ОТ пользователей--
Конечно, ключевая информация, необходимая для выполнения этой атаки, заключается в том, что существует таблица с именем 9.0003 пользователей с двумя столбцами, называемыми имя пользователя
и пароль
. Без этой информации вам пришлось бы пытаться угадать имена таблиц и столбцов. Фактически, все современные базы данных предоставляют способы изучения структуры базы данных, чтобы определить, какие таблицы и столбцы она содержит.
ПРАКТИК Атака UNION с внедрением SQL, получение данных из других таблиц
Подробнее
- Исследование базы данных при атаках с внедрением SQL
В предыдущем примере предположим, что запрос возвращает только один столбец.
Вы можете легко получить несколько значений вместе в этом одном столбце, объединив значения вместе, в идеале включив подходящий разделитель, чтобы вы могли различать объединенные значения. Например, в Oracle вы можете отправить ввод:
' UNION SELECT имя пользователя || '~' || пароль ОТ пользователей--
Здесь используется двойная последовательность ||
, который является оператором конкатенации строк в Oracle. Введенный запрос объединяет значения полей имя пользователя
и пароль
, разделенные символом ~
.
Результаты запроса позволят вам прочитать все имена пользователей и пароли, например:
...
администратор~s3cure
Винер~Питер
Карлос ~ Монтойя
...
Обратите внимание, что разные базы данных используют разный синтаксис для выполнения конкатенации строк. Дополнительные сведения см. в памятке по SQL-инъекциям.
ЛАБОРАТОРИЯПРАКТИК Атака UNION с внедрением SQL, получение нескольких значений в одном столбце
Истории из Daily Swig о внедрении SQL
Эта страница требует JavaScript для улучшения взаимодействия с пользователем.
Познакомьтесь с телер-ваф
Промежуточное программное обеспечение HTTP, ориентированное на безопасность, для платформы Go 09 января 2023 г. Познакомьтесь с телер-ваф Промежуточное программное обеспечение HTTP, ориентированное на безопасность, для платформы GoАвтомобильные компании массово подвержены веб-уязвимостям
04 января 2023 г. Автомобильные компании массово подвержены веб-уязвимостям Гранд Хак АвтоВзлом синтаксиса JSON позволил полезной нагрузке SQLi прокрасться мимо WAF
09 декабря 2022 г. Взлом синтаксиса JSON позволил полезной нагрузке SQLi прокрасться мимо WAF Пять поставщиков действуют, чтобы помешать общему взломуОшибки Zendesk Explore открыли дверь к грабежу аккаунта
15 ноября 2022 г. Недостатки Zendesk Explore открыли дверь к грабежу аккаунта Исправленные уязвимости SQLi и логического доступа представляли серьезную опасностьSQL-инъекции на основе объединения и способы предотвращения этих атак
13 июня 2022 г.
9min read
Sudip Sengupta
В этой статье:
HTTPSHTTP
Анализируем https://example.com
Цель сканирования https://example.com
Crashtest Security Suite будет проверять:
Раскрытие информации Известные уязвимости Неправильная конфигурация SSL Открытые портыЗавершите запрос на сканирование
Пожалуйста, заполните ваши данные, чтобы получить
быстрый аудит безопасности по электронной почте.