TGViewer
Пингискок Пингискок @rmrf_0 · 618 subscribers
Post #10 413
Как 5.6 МБ JavaScript раскрыли скрытый бэкенд и подпись произвольных платежей
Аудит Web3-проекта с крипто-пресейлом. Фронтенд - React SPA за Cloudflare. Ни одного видимого API-эндпоинта. Казалось бы - нечего ломать.

React SPA отдаёт один index.html на любой путь. WordPress-поддомены закрыты Cloudflare. REST API отключён. Регистрация отключена. Живых эндпоинтов - ноль.

Но у Web3-проектов есть особенность: вся логика взаимодействия с блокчейном живёт на клиенте. Кошелёк подключается из браузера, адреса контрактов и RPC-вызовы формируются на фронте. Сервер не может это спрятать. Когда видишь пустую SPA-оболочку без единого API - это не тупик. Это приглашение читать бандлы.

Vite нарезал код на 10 чанков. Source maps недоступны (все .js.map возвращают HTML фронтенда - SPA catch-all). Только ручной разбор минифицированного кода.

app-[hash].js        434 KB   - бизнес-логика, роуты, платежи
main-[hash].js 576 KB - WalletConnect, UI
wallet-libs-[hash] 3.5 MB - кошельки, провайдеры, цепочки
crypto-libs-[hash] 637 KB - криптобиблиотеки


Ищу строки: https://, baseURL, fetch(, axios, endpoint. В чанке бизнес-логики нахожу базовый URL, который нигде не фигурировал - ни в DNS, ни в документации, ни в HTML. Бэкенд жил на полностью отдельном домене.

Один GET на /health подтвердил:

{"status":"ok","info":{"mongodb":{"status":"up"},"google":{"status":"up"}}}


CORS настроен правильно (только домен фронтенда), но GET-эндпоинты не требуют аутентификации - прямые curl-запросы работают.

Дальше - по всему JS-бандлу собираю пути, параметры, заголовки. Восстановил 17 эндпоинтов. Каждый проверил вручную - какие требуют авторизацию, какие нет, какие принимают пользовательский ввод и как его валидируют.
Большинство GET-эндпоинтов оказались открыты: финансовая конфигурация пресейла, баланс любого кошелька по адресу (IDOR), статистика стейкинг-пулов, валидация промокодов (перебор). Неприятно, но не критично.

Самый интересный - POST /wert.
Wert - фиатный шлюз. Пользователь платит картой, Wert выполняет on-chain транзакцию. Бэкенд подписывает параметры платежа, и эта подпись говорит Wert: «транзакция легитимна».

Эндпоинт /wert принимает POST с параметрами и возвращает подписанные данные. Проверяю - что если подменить адрес смарт-контракта?

# Отправляю произвольный:
curl -X POST https://<backend>/wert \
-H "Content-Type: application/json" \
-d '{"sc_address":"0x0000000000000000000000000000000000000001",
"sc_input_data":"0xdeadbeef",
"commodity_amount":100}'


Ответ: валидная подпись.

Подменяю sc_address на произвольный контракт - подписано. Подменяю sc_input_data на произвольные calldata - подписано. Ставлю commodity_amount = -1 - подписано. Ставлю 0 - тоже подписано.

Сервер подписывает всё. Нет валидации адреса, нет проверки calldata, нет ограничений на сумму. Если Wert доверяет подписи без собственной валидации - атакующий подменяет sc_address на свой контракт, получает подпись, инициирует платёж, и средства пользователя уходят не туда.

Бонус: RPC-ключ с debug-доступом к 5 блокчейнам

В том же бандле - API-ключ RPC-провайдера. Рабочий на 5 сетях (BSC, Ethereum, ETH Sepolia, Solana Mainnet, Solana Devnet) с premium-методами:

# debug_traceBlockByNumber - трассировка ВСЕХ транзакций блока
# (опкоды, стек, память, internal calls)
curl -X POST "https://<rpc>/$KEY" \
-d '{"method":"debug_traceBlockByNumber","params":["latest",{}]}'
# Получаю 200 OK

# txpool_status - мемпул
# {"pending":"0x2d","queued":"0x2ee"}


Debug + archive - premium-тариф. Вектор для MEV/фронтраннинга + нагрузка на платный план проекта.
  • 🔥 9
  • ❤ 5
  • ⚡ 1
  • 🗿 1
More from @rmrf_0
  1. May 1, 2026Белый хакер: “может, всё-таки responsibly disclose?” Google: давай! memory corruption - 50…
  2. Apr 13, 2026DeFi-протоколы не взламывают. Они просто не закрыты. Омар рассказал кейс про то как их AI-…
  3. Apr 8, 2026Claude Mythos.. .. еще не выпущен, но опубликовали исследование про него: https://red.anth…
  4. Apr 6, 2026Как КНДР полгода играла в квант-фонд и вынесла $285M из Drift Drift - крупнейший перпетуал…
  5. Apr 3, 2026Мое лицо когда закрыл серию статей (думайте, какое именно лицо мое) Закрыл, да не полность…
  6. Mar 28, 2026Продолжение серии про JWT - шесть новых статей Криптография, шифрование, библиотеки, OAuth…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →