CIOlogia Безопасность бизнеса · не на словах, а с доказательствами
← Все разборы Информационная безопасность

Утечка в Revolut и дыра у оптовика: один и тот же баг, разный масштаб денег

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

Разбор CIOlogia
Утечка в Revolut и дыра у оптовика: один и тот же баг, разный масштаб денег

Новость про Revolut — утечка документов, IBAN, истории операций, включая активность по криптовалютам и пожертвованиям — выглядит как история про хакеров международного уровня. На деле механика почти всегда банальнее: доступ, который никто вовремя не отозвал, пароль, который никто не менял, и учётка, которая продолжает жить своей жизнью после увольнения сотрудника или окончания контракта с подрядчиком. Ниже — разбор похожего по сути, но в разы меньшего по масштабу случая: платёжный агрегатор, оптовая компания, семь человек с доступом к личному кабинету и ни одного факта ротации паролей за пять лет.

Крючок: письмо от клиента

Один из постоянных заказчиков написал напрямую: «Откуда у вас данные о моих платежах за прошлый год, если я их вам не присылал?» У него были детали, которые он точно не сообщал компании — суммы операций, даты, номер счёта. Это классический признак того, что данные ушли не через утечку у самого клиента, а через точку, где эти данные хранились централизованно — то есть через личный кабинет агрегатора у поставщика.

Где была дыра

Доступ к личному кабинету платёжного агрегатора имели семь человек, включая бухгалтера, уволенного два года назад. Пароль не менялся вообще — передавался новым сотрудникам «по наследству». Двухфакторной аутентификации не было: только логин и пароль, который к тому же лежал открытым текстом в файле на общем Яндекс.Диске. Доступ к этому диску имел весь отдел продаж, включая подрядчика, который делал разовую задачу полгода назад и так и не был отключён от общих ресурсов.

Уволенный сотрудник — это не просто человек, который перестал приходить в офис. Это доступ, который продолжает жить своей жизнью, если его не закрыть.

Как это эксплуатируется

Ниже — типовая цепочка действий, которой пользуется атакующий (или недобросовестный бывший сотрудник) при таком раскладе. Это не пошаговая инструкция под конкретную жертву, а стандартный workflow, который применяется в подобных ситуациях сплошь и рядом.

Шаг 1. OSINT и разведка периметра

Сначала собирается информация о том, какими сервисами пользуется компания — платёжный агрегатор, CRM, облачное хранилище. Домены и поддомены ищутся автоматически:

subfinder -d target-company.ru -silent | httpx -title -status-code

[200] https://target-company.ru [Главная]
[200] https://cabinet.agregator-payments.ru [Личный кабинет]
[403] https://admin.target-company.ru [Forbidden]

Шаг 2. Поиск утёкших публичных ссылок на файлообменники

Файлы с паролями, лежащие на общих дисках, регулярно индексируются поисковиками или находятся через google dorking по характерным URL-паттернам публичных ссылок:

site:yadi.sk "пароль" OR "доступ" OR "агрегатор"
site:disk.yandex.ru filetype:xlsx "логин" "пароль"

Если публичная ссылка когда-либо была создана «на всякий случай» и не отозвана — файл индексируется и остаётся доступным годами, даже после того как формально доступ «закрыли» для сотрудников.

Шаг 3. Проверка утечек по учётным записям (credential stuffing)

Если пароль от личного кабинета агрегатора совпадает с паролем, засветившимся в старых утечках (а при отсутствии ротации 5 лет — вероятность высокая), он проверяется по базам скомпрометированных паролей и через автоматизированный подбор:

hydra -l buhgalter@company.ru -P rockyou.txt cabinet.agregator-payments.ru https-post-form \
  "/login:email=^USER^&password=^PASS^:Неверный пароль"

[ATTEMPT] target cabinet.agregator-payments.ru - login "buhgalter@company.ru" - pass "Company2019!"
[22][http-post-form] host: cabinet.agregator-payments.ru login: buhgalter@company.ru password: Company2019!

При включённой двухфакторной аутентификации этот вектор закрывается почти полностью — брутфорс упирается в одноразовый код. Именно поэтому отсутствие 2FA в связке с не меняющимся годами паролем — критическая комбинация.

Шаг 4. Проверка заголовков и конфигурации личного кабинета

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

curl -sI https://cabinet.agregator-payments.ru/login

HTTP/1.1 200 OK
Set-Cookie: PHPSESSID=a1b2c3d4e5; path=/
Server: nginx/1.18.0
X-Frame-Options: (отсутствует)
Strict-Transport-Security: (отсутствует)

Отсутствие флагов Secure, HttpOnly у сессионной куки и заголовка Strict-Transport-Security — типичный признак того, что панель настраивалась «по умолчанию» много лет назад и с тех пор не аудировалась. Это классифицируется как CWE-522 (Insufficiently Protected Credentials) и попадает в категорию OWASP A07:2021 — Identification and Authentication Failures.

Шаг 5. Выгрузка данных после входа

После успешного входа с легитимными, но давно не отозванными учётными данными, атакующий не «взламывает» ничего дальше — он просто пользуется штатным функционалом экспорта, который есть в любом личном кабинете агрегатора:

curl -s -b "PHPSESSID=a1b2c3d4e5" \
  "https://cabinet.agregator-payments.ru/api/v1/transactions/export?period=12m&format=csv" \
  -o history_export.csv

wc -l history_export.csv
2841 history_export.csv

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

Полутехнические пруфы, на которые стоит смотреть

  • Логи входа без записи о геолокации/устройстве — невозможно отличить «свой» вход от чужого;
  • Отсутствие ограничения по количеству одновременных активных сессий на аккаунт;
  • Публичные ссылки на файлы в облаке без срока действия (Яндекс.Диск по умолчанию делает ссылку бессрочной);
  • Отсутствие журнала выданных и отозванных доступов к финансовым сервисам — типичная ситуация, когда «кто имеет доступ» невозможно быстро проверить даже собственнику бизнеса.

Что и почему сработало бы дальше

Получив выгрузку истории операций, реквизиты счетов и переписку по сделкам, атакующий получает материал для нескольких сценариев одновременно: перепродажа данных на теневых форумах, таргетированный BEC-фишинг («смена реквизитов для оплаты» от имени поставщика — с реальными суммами и датами из выгрузки, что резко повышает доверие жертвы), либо прямой шантаж компании раскрытием факта утечки. Именно последний сценарий стал реальностью в приведённом кейсе — не взлом ради взлома, а потеря доверия клиента и разрыв контракта.

Сколько это стоило бизнесу

Точно установить, кто и как воспользовался утечкой, не удалось — вероятно, данные были проданы третьим лицам. Но один клиент уже разорвал отношения, прямо указав причину: «Не доверяю вашей защите данных». Для оптовой компании со средним чеком 350 000 ₽ в квартал — это не абстрактный репутационный риск, а конкретно посчитанная потеря. Отдельно стоит риск штрафов за утечку персональных данных, которые по действующему законодательству могут доходить до миллионов рублей за повторные нарушения.

Как закрыть

  1. Сменить все пароли доступа к агрегатору немедленно, не дожидаясь планового цикла ротации;
  2. Убрать файл с паролями с общего диска и провести ревизию всех активных публичных ссылок:
    # проверка всех публичных ссылок аккаунта через API Яндекс.Диска
    curl -H "Authorization: OAuth <token>" \
      "https://cloud-api.yandex.net/v1/disk/resources/public" \
      | jq '.items[] | {path, public_url}'
  3. Включить двухфакторную аутентификацию через приложение (TOTP) для всех сервисов, где хранятся платёжные и персональные данные;
  4. Провести полный аудит доступов и немедленно отключить учётки уволенного бухгалтера и подрядчика с закрытым контрактом;
  5. Настроить алерты на вход с нового устройства или IP — простейший вариант: webhook в Telegram-бота при каждом новом логине;
  6. Ввести регулярный ревью доступов к финансовым сервисам, CRM и облачным хранилищам — раз в квартал, с фиксацией результата в чек-листе, а не «на память».

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

Почему это не редкость

История с Revolut — тот же самый принцип, только с другим количеством нулей: утекли документы, IBAN, история операций, данные о криптоактивностях и пожертвованиях клиентов. Разница в том, что у крупного финтеха есть служба безопасности, которая способна расследовать инцидент и локализовать масштаб. У малого бизнеса такой службы нет — есть только владелец, бухгалтер и убеждение, что «пароль от личного кабинета не так важен, как касса».

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