ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2
Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей. Здесь обсуждаются безопасность, программирование, технологии и многое другое. Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
Вернуться   Форум АНТИЧАТ > ИНФО > Статьи > Чужие Статьи
   
 
 
Опции темы Поиск в этой теме Опции просмотра

SQL injection в MySql сервере версии 3,x
  #1  
Старый 04.06.2006, 13:37
Аватар для bandera
bandera
Познающий
Регистрация: 02.06.2006
Сообщений: 66
Провел на форуме:
870911

Репутация: 69
По умолчанию SQL injection в MySql сервере версии 3,x

Статья старая, но думаю актуальна.


SQL инъекция в MySQL сервере третей версии

24 ноября, 2004

Автор: Phoenix

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

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

Такая ситуация привела к мнению, что в MySQL 3 SQL инъекция в принципе не может ничем грозить.

Даже некоторыми хакерами считается что, если на сервере используется СУБД MySQL третей версии, то это случай безнадежный. Однако, у меня есть свое мнение на этот счет, и я хочу показать, что в некоторых ситуациях данный вопрос имеет свой ответ.

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

Три или четыре

И так, обнаружен факт SQL инъекции. Как определить что это действительно, MySQL, и определить версию MySQL сервера.

Допустим, инъекция имеет место в запросе, типа http://localhost/test.php?id=1, в параметре id. Если страница выводит некоторое содержание, соответствующее введенному идентификатору, то можно предположить, что имеет место инъекция после where запроса. Мы считаем, что факт наличия SQL инъекции в нашем случае выявлен любыми средствами, о которых описано в настоящее время немало, и действительно имеет место.

Допустим, нападающий заметил, что он может внедрять булевы конструкции в запрос, и они явно влияют на результат запроса. Так, например http://localhost/test.php?id=1+AND+0, выведет страницу без содержания, а http://localhost/test.php?id=1+AND+1, выведет страницу, аналогичную странице с переданным параметром id=1.

Имя этот факт, уде можно составить серию запросов к серверу с целью подтвердить (или опровергнуть) предположение, что это СУБД MySQL, и, случае, если это действительно MySQL, выявить версию сервера.

И для того и для другого можно использовать особенность реализации SQL в MySQL. А именно, содержание специальных скобок вида /*!NNNNN … */ будет выполнено обычным образом, в MySQL тогда и только тогда, когда полная версия сервера (записанная подряд, без точек, с ведущими нолями в подверсиях), больше или равна чем NNNNN. В противном случае эта запись будет воспринята как комментарий.

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

Учитывая, что, в любом случае, записанная таким образом версия mySQl сервера будет больше, чем 00000, то запись /*!00000 Any_SQL_commands */ будет эквивалента Any_SQL_commands, в любом запросе в MySQL. Одновременно, эта запись будет эквивалента комментарию в любых других СУБД.

Таким образом, можно однозначно определить MySQL, в нашем примере, сделав следующий запрос: http://localhost/test.php?id=1+/*!00000+AND+0+*/.

Вывод пустой страницы (эквивалент запроса http://localhost/test.php?id=1+AND+0), будет однозначно свидетельствовать о том, что имеет место взаимодействие действительно с СУБД MySQL. В противном случае, это, скорее всего не MySQL. Следует учесть, что все это верно только в идеальной ситуации – отсутствие фильтрации и т.п., что однако, не редкость.

Используя этот прием, можно однозначно определит, имеет СУБД MySQL в нашем случае версию 3.x или 4.x. Достаточно сделать следующий запрос: http://localhost/test.php?id=1+/*!40000+AND+0+*/. Этот запрос вернет пустую страницу (в нашем примере), тогда и только тогда, когда версия MySQL сервера 4.x.

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

http://localhost/test.php?id=1+/*!40000+AND+0+*/

http://localhost/test.php?id=1+/*!41000+AND+0+*/

http://localhost/test.php?id=1+/*!40500+AND+0+*/

http://localhost/test.php?id=1+/*!40300+AND+0+*/

http://localhost/test.php?id=1+/*!40400+AND+0+*/



http://localhost/test.php?id=1+/*!40311+AND+0+*/

http://localhost/test.php?id=1+/*!40312+AND+0+*/

В случае, если предпоследний запрос вернул пустую страницу, о последний вернул страницу, аналогичную http://localhost/test.php?id=1, то можно однозначно судить, что MySQL сервер имеет версию 4.3.12

Еще один метод определения версии MySQL сервера состоит в использовании функции version(), которая возвращает строку с текущей версией. Этот метод можно применять в случаях, если какие либо причины мешают использовать предыдущий метод. Например, происходит фильтрация символов /.

К примеру, если запрос http://localhost/test.php?id=1+AND+(version()+like+’4%’) возвратит страницу, соответствующую идентификатору id=1, то можно однозначно судить о том, что MySQL сервер имеет четвертую версию.

Если применение кавычек мешает фильтрация, то вместо строки можно использовать функцию, которая в качестве значения вернет необходимую строку. Можно использовать char(), функцию, которая возвращает строку, соответствующую из символов с ASCII кодами которые приняты в качестве аргументов.

Пример. Запрос http://localhost/test.php?id=1+AND+(version()+like+char(25,34)), будет аналогичен предыдущему, но не будет содержать кавычек.

Пользуясь этим примером можно выявить и полную версию СУБД MySQL, либо последовательно подбирая все символы, либо пользуясь дихотомическим поиском, используя сравнение строк в лексикографическом порядке.

Стоит отметить, что подомным же образом можно подобрать и значения других функций, которые могут быть интересны нападающему. User() – возвращает имя пользователя MySQL из под которого произошло подсоединение с базой данных. Database() – возвращает имя текущей базы данных.

Даже, если инъекция происходит в произвольном запросе в произвольном месте, выяснить MySQl это или нет, и версию MySQL аналогичным образом можно, например внедряя внутри этих скобок значения, которые однозначно “испортят” запрос.

http://localhost/test.php?id=1+/*!40000+AND+blablabla+*/, и нападающий сможет узнать, выполнились ли инструкции (которые не являются синтаксически верными инструкциями MySQL), или нет, по тому, нормально функционирует скрипт при таком запросе (инструкции были восприняты как комментарий), или нет (инструкции были проинтерпретированы как часть запроса).

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

Инъекция после where

SQL инъекция после ключевого слова where является одним из наиболее распространенных случаев. SQL запрос в этом случае имеет примерно следующий вид select … from … where … rowN=$row …, где вставляется в запрос без надлежащей фильтрации.

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

Допустим имеет место SQL инъекция в скрипте http://localhost/test.php?id=1, который выводит в броузер некоторую информацию о соответствующем пользователе. Естественно, пароль пользователя не выводиться. Покажем, каким образом в MySQL 3 можно узнать как пароль произвольного пользователя, так и пароль целевого пользователя. Считаем, что пароль храниться в открытом виде в той же таблице, в которой и хранятся и остальные параметры пользователя. Те, имя этой таблицы явно участвует в запросе.

Если в таблице храниться хеш пароля, та нападающему станет известен хеш, который надо будет еще расшифровать.

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

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

Вряд ли, более чем в одной таблице будут присутствовать такие столбцы, как login или pass и т.п, так что подбирать имя таблицы в большинстве случаев не необходимо.

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

http://localhost/test.php?id=1+or+password=’abc’

http://localhost/test.php?id=1+or+pass=’abc’

http://localhost/test.php?id=1+or+passwd=’abc’

http://localhost/test.php?id=1+or+u.password=’abc’

http://localhost/test.php?id=1+or+user.password=’abc’



Если результатом одного из представленных запросов будет страница, идентичная странице с переданным идентификатором id=1, то это будет свидетельствовать о том, что имя столбца, и, возможно, имя таблицы найдено успешно.

Допустим, интересующее нас имя столбца – pass,те второй запрос вернул положительный результат.

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

http://localhost/test.php?id=9999999+or+pass+like+’a%’ (-)

http://localhost/test.php?id=9999999+or+pass+like+’b%’ (-)



http://localhost/test.php?id=9999999+or+pass+like+’p%’ (+)

http://localhost/test.php?id=9999999+or+pass+like+’pa%’ (+)

http://localhost/test.php?id=9999999...ike+’paa%’ (-)



http://localhost/test.php?id=9999999...ike+’pas%’ (+)



http://localhost/test.php?id=9999999...’pas21m1%’ (+)

http://localhost/test.php?id=9999999...pas21m1_%’ (-)

Запись, соответствующая идентификатору 9999999, не существует в базе данных, в этом стоит убедиться заранее.

Плюсом отмечен положительный результат запроса. Положительным считается результат, выводящий параметры хоть какого то пользователя в броузер. Отрицательный (-) результат имеет место в случае, если выведена страница, идентичная передачи id=9999999, те пустая страница.


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

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

При подборе символов пароля таким способом следует помнить, что в пароле могут присутствовать как символы английского алфавита, так и цифры и другие символы. В случае, если в пароле присутствует символ _ или %, то при их подборе внутри like, эти символы следует мнемонизировать обратной косой.

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

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

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

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

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

http://localhost/test.php?id=9999999+or+(id=1), или

http://localhost/test.php?id=9999999+or+(login=’admin’)

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

http://localhost/test.php?id=9999999+or+(id=1+AND+pass+like+’a% ) http://localhost/test.php?id=9999999+or+(id=1+AND+pass+like+’b% )

и так далее.

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

http://localhost/test.php?id=9999999+or+(id=1+AND+pass+>=+’k’) (-)

http://localhost/test.php?id=9999999+or+(id=1+AND+pass+>=+’g’) (+)

http://localhost/test.php?id=9999999+or+(id=1+AND+pass+>=+’h’) (-)

http://localhost/test.php?id=9999999+or+(id=1+AND+pass+>=+’fk’)

и так далее, последовательно перебирать каждую букву.

Стоит отметить, что в любом описанном в этой статье случае, строковую константу, заключенную в кавычки, можно заменить на функцию char(), с соответствующими аргументами.

Последний раз редактировалось bandera; 04.06.2006 в 13:41..
 
Ответить с цитированием
 



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Обнаружение Sql инъекций в Oracle, часть вторая k00p3r Чужие Статьи 0 13.06.2005 11:26
Sql инъекция и Oracle, часть первая k00p3r Чужие Статьи 0 13.06.2005 11:23
Защищаем MySql. Шаг за шагом k00p3r Чужие Статьи 0 13.06.2005 11:18
SQL Injection в Oracle k00p3r Чужие Статьи 0 12.06.2005 12:41



Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ