Статья Bcrypt взлом паролей: как утекают хэши с Dragonica и почему это проще, чем кажется

Две видеокарты RTX 3090 на тёмном антистатическом коврике, подсвеченные бирюзовым светом монитора. На задней панели карты лазерная гравировка с хешем bcrypt и пометкой CRACKED.


На CTF в прошлом году попался дамп базы частного сервера Dragonica - около 40 тысяч аккаунтов, bcrypt-хэши с cost factor 10. Организаторы закладывали на этап крекинга два дня. Две RTX 3090, словарь rockyou плюс кастомный геймерский wordlist с правилами мутации - и за 14 часов удалось восстановить примерно 1500 паролей. Четыре процента от базы. Звучит мало, пока не прикидываешь последствия: для credential stuffing атаки на Steam, Discord и Gmail этих 1500 пар логин-пароль хватает с запасом. Bcrypt - хороший алгоритм. Но «хороший алгоритм» и «безопасное хранение паролей» - не синонимы, когда cost factor стоит по дефолту, а геймеры ставят пароли вроде dragonica2023.

Утечка базы данных игры: от fingerprinting до password hash dump​

Частные серверы Dragonica, Lunaris и подобные проекты - реверснутые серверные эмуляторы, обвешанные самописными веб-панелями. Типовой стек: PHP 5.x–7.x, MySQL/MariaDB, phpMyAdmin для управления базой, иногда WordPress или самописная CMS для лендинга. Безопасность тут - дело десятое: разработчики заняты геймплеем и донатом, а не харденингом инфраструктуры.

Fingerprinting таких серверов - задача на пять минут. Стандартный nmap -sV выявляет открытые порты MySQL (3306) и phpMyAdmin (80/443). Заголовки HTTP-ответов выдают версию PHP, наличие X-Powered-By, иногда debug-информацию. Shodan по запросу с названием игры выводит десятки частных серверов с предсказуемой инфраструктурой.

[Применимо: внешний пентест, legacy-инфраструктура]

Типичные векторы, через которые происходит утечка паролей игрового сервера:

SQL-инъекции в панелях управления (Exploit Public-Facing Application, T1190, Initial Access). Регистрация, восстановление пароля, голосование за сервер - любая форма, работающая с базой. На частных серверах prepared statements встречаются реже, чем прямая конкатенация пользовательского ввода в SQL-запросах. Один UNION-based SQLi в форме логина - и таблица accounts с хэшами на экране.

Открытый phpMyAdmin (A05:2021, Security Misconfiguration по OWASP). Встречается удивительно часто. Админ ставит phpMyAdmin «для себя», забывает ограничить доступ - и /phpmyadmin/ висит на весь интернет. Подключение с root без пароля или со стандартным root:root - и вся база на ладони.

Слабые конфиги MySQL (Credentials In Files, T1552.001, Credential Access). MySQL слушает на 0.0.0.0:3306, пароль root пустой или стандартный. Удалённое подключение через mysql -h target -u root - и дамп таблицы с хэшами занимает секунды.

Устаревшие компоненты (A06:2021, Vulnerable and Outdated Components по OWASP). PHP 5.6 с известными RCE, старые версии phpMyAdmin, непропатченные плагины CMS - стандартные точки входа для initial access.

После получения доступа к базе (Databases, T1213.006, Collection) атакующий экспортирует таблицу с учётными данными. В Dragonica-подобных проектах это обычно accounts или users - логин, email, bcrypt-хэш пароля. Дальше начинается офлайн-работа, детектировать которую на стороне сервера уже невозможно.

Полная цепочка атаки​

Recon (fingerprinting веб-панели, определение стека) -> initial access (SQLi, открытый phpMyAdmin) -> collection (дамп таблицы с хэшами) -> credential access (Password Cracking, T1110.002 - офлайн-крекинг bcrypt) -> использование восстановленных паролей (Valid Accounts, T1078) для credential stuffing на сторонних сервисах. Каждый этап после дампа разбираем ниже.

Bcrypt хэши безопасность: что внутри и почему cost factor решает​

1781068606259.webp

Прежде чем крекать - нужно понимать, что крекаешь. Типичный bcrypt-хэш из дампа: $2a$10$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW.

Разбор по частям (на основе спецификации bcrypt и данных Wikipedia):
  • $2a$ - идентификатор алгоритма и версии. Варианты: $2a$, $2b$ (исправление бага с длиной пароля >255 байт в OpenBSD, февраль 2014), $2y$ (исправление бага обработки 8-битных символов в PHP-реализации crypt_blowfish, июнь 2011). Для взлома хэшей паролей разницы нет - Hashcat и JtR обрабатывают все три одинаково.
  • 10 - cost factor (work factor). Означает 2^10 = 1024 итерации ключевого расписания EksBlowfish. Это дефолт в большинстве реализаций: Go bcrypt использует DefaultCost = 10 (по данным pkg.go.dev), PHP password_hash() - тоже 10.
  • 22 символа - base64-кодированная 128-битная соль (bcrypt использует собственный алфавит base64, отличный от RFC 4648).
  • 31 символ - base64-кодированный хэш (первые 23 байта из 24-байтного результата).
Bcrypt спроектирован Niels Provos и David Mazières на основе шифра Blowfish и представлен на USENIX в 1999 году (по данным Wikipedia). Ключевой механизм - EksBlowfishSetup: алгоритм 2^cost раз прогоняет ExpandKey с чередованием пароля и соли, после чего шифрует строку OrpheanBeholderScryDoubt 64 раза в режиме ECB. Результат и есть итоговый хэш.

Три свойства bcrypt, критичных для password cracking​

Ограничение в 72 байта. Bcrypt обрабатывает только первые 72 байта пароля - остальное молча отбрасывается. В bcrypt 5.0.0 для Python (по данным PyPI) передача пароля длиннее 72 байт вызывает ValueError вместо тихого усечения. Для игровых серверов это некритично - пароли геймеров редко длиннее 15 символов. Но если разработчик решил хэшировать через sha256(password) + bcrypt, 72-байтное ограничение перестаёт быть проблемой - на входе всегда 44 символа base64.

Встроенная соль. Каждый хэш содержит уникальную 128-битную соль. Rainbow table атака полностью неприменима. Предрассчитанные таблицы бесполезны - каждый пароль крекается индивидуально.

Экспоненциальный cost. Увеличение cost на 1 удваивает время вычисления. Cost 10 - 1024 итерации. Cost 12 - 4096, в 4 раза медленнее. Cost 14 - 16384, в 16 раз медленнее. По данным из статьи на Habr, при cost 12 генерация одного хэша занимает 0.2–0.3 секунды - это нижний порог рекомендации OWASP (вычисление хэша должно занимать менее одной секунды, но не менее ~250 мс). Большинство частных игровых серверов сидят на дефолтном cost=10 - 0.05 секунды за хэш, в 4–6 раз быстрее рекомендованного минимума. По меркам 2025 года - просто подарок для атакующего.

Брутфорс bcrypt хэшей: hashcat bcrypt и john the ripper bcrypt на практике​

1781068632643.webp

Требования к окружению​

  • GPU: NVIDIA с CUDA - RTX 3090 или RTX 4090. AMD через OpenCL работает, но на bcrypt значительно медленнее.
  • VRAM: минимум 8 ГБ.
  • ОС: Kali Linux 2024.x / Ubuntu 22.04+, или Windows 10+ с CUDA-драйверами.
  • Hashcat: 6.2.6+ (активно поддерживается, github.com/hashcat/hashcat).
  • John the Ripper: jumbo 1.9.0-jumbo-1+ (активно поддерживается, github.com/openwall/john).
  • RAM: 8 ГБ минимум, 16 ГБ рекомендуется для работы с крупными словарями.

Реалистичные скорости взлома хэшей паролей

Bcrypt намеренно медленный - в этом весь смысл. По данным исследования Hive Systems (опубликованы на anti-malware.ru и codeby.net), при использовании 12 GPU NVIDIA RTX 4090 пароли до 7 символов взламываются за несколько часов. 11-символьный пароль при bcrypt с cost=10 - за 10 часов. Для сравнения: тот же 11-символьный пароль при MD5 ломается мгновенно.

На одном RTX 3090 при cost=10 реалистичная скорость - примерно 25–30 H/s (хэшей в секунду). RTX 4090 даёт вдвое больше. Это не миллиарды H/s, как при MD5/SHA-256. Но для словарной атаки с мутациями по словарю из 500 тысяч записей - 5–6 часов работы. Hashcat проверяет каждого кандидата против всех хэшей в файле параллельно, так что размер дампа на общее время влияет меньше, чем размер словаря.

Hashcat: режим 3200​

Hashcat использует режим 3200 для всех вариантов bcrypt ($2a$, $2b$, $2y$). Словарная атака с правилами мутации:
Bash:
hashcat -m 3200 -a 0 hashes.txt rockyou.txt -r rules/best64.rule -w 3 --status --status-timer=60
Здесь -a 0 - словарная атака, -r rules/best64.rule - набор правил мутации (добавление цифр, замена символов, смена регистра), -w 3 - максимальная нагрузка GPU, --status-timer=60 - прогресс каждую минуту. Файл hashes.txt содержит по одному хэшу на строку.

Самый эффективный подход - cascading rules: сначала best64.rule (64 правила, быстрая проверка базовых мутаций), затем d3ad0ne.rule (~34 тысячи правил для глубокой проработки). Порядок важен: при 30 H/s каждое лишнее правило стоит реального времени.

John the Ripper​

JtR в jumbo-версии поддерживает bcrypt нативно и автоматически определяет формат по префиксу:
Bash:
john --format=bcrypt --wordlist=rockyou.txt --rules=All hashes.txt
На CPU JtR удобнее для небольших списков (десятки хэшей), но для серьёзных объёмов GPU через Hashcat выигрывает на порядок. Я обычно запускаю JtR для быстрой проверки «а вдруг кто-то поставил password123» - и если есть попадания в первые минуты, переключаюсь на Hashcat с тяжёлыми правилами.

Геймерские пароли: почему словарная атака работает лучше брутфорса​

Чистый брутфорс bcrypt - плохая стратегия. Полный перебор 8-символьного пароля с mixed charset при 30 H/s займёт столетия. Словарная атака с мутациями - другое дело.

Типичные пароли геймеров предсказуемы до боли: ник + год рождения (darkelf1998), название класса или сервера + цифры (warrior123, lunaris2023, dragonica!), стандартные игровые термины (guildmaster, pvpking). Комбинация rockyou с кастомным геймерским словарём и правилами мутации покрывает значительную долю базы в первые часы.

Для формирования кастомного wordlist: названия классов и рас из Dragonica, популярные гильдии с форумов сервера, никнеймы из топ-рейтингов. Добавить правила мутации - и вероятность попадания вырастает кратно по сравнению с чистым rockyou. На практике я всегда трачу 20–30 минут на разведку форума перед крекингом - это окупается первыми же попаданиями.

Ограничения техники​

Работает если: cost=10 или ниже, пароли предсказуемые, доступен GPU с CUDA.

Не работает если: cost=12+, пароли случайные или длиннее 12 символов со спецсимволами. При cost=14 даже RTX 4090 выдаёт около 3–4 H/s. Bcrypt взлом паролей эффективен только при совпадении двух условий: низкий cost factor и предсказуемые пароли.

Credential stuffing атака: от хэшей к реальным аккаунтам​

Восстановленные пароли - не конечная цель, а ресурс для credential stuffing (Valid Accounts, T1078). Геймеры переиспользуют пароли повсюду: один и тот же пароль на игровом сервере, в Discord, Steam и Gmail.

В отличие от утечек корпоративных систем, дампы игровых серверов часто содержат email-адреса, которые пользователи считают основными. Геймеры не заводят отдельные почтовые ящики для каждого сервера - это тот же Gmail или Mail.ru, через который привязан Steam, Discord, иногда рабочая почта. Один восстановленный пароль может открыть доступ к целой цепочке аккаунтов.

Цепочка после крекинга: из дампа берётся email, сопоставляется с восстановленным паролем. Автоматизированные инструменты проверяют пары на десятках сервисов. Доступ к Gmail открывает сброс паролей на других платформах. Discord-аккаунт с подпиской Nitro монетизируется на чёрных маркетплейсах. И всё это - из-за пароля warrior123 на забытом частном сервере.

Согласно OWASP A02:2021 (Cryptographic Failures), слабая криптографическая защита паролей ведёт к компрометации чувствительных данных. Утечка базы данных игры с bcrypt-хэшами - первое звено цепочки, которая заканчивается далеко за пределами игрового сервера.

Защита от утечки паролей игрового сервера: чеклист

📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме

Абсолютное большинство утечек с частных серверов происходит не из-за bcrypt уязвимостей, а из-за тривиальных ошибок конфигурации: открытые порты, дефолтные пароли, отсутствие prepared statements. Bcrypt при правильной настройке - серьёзное препятствие. Bcrypt с cost=10 и паролями из словаря - формальность.

Есть устойчивое мнение, что bcrypt «не ломается». Формально - верно: при cost=12+ и случайном 14-символьном пароле полный перебор нерентабелен на любом доступном железе. Но за несколько лет участия в CTF и разборов утечек игровых проектов я ни разу не встретил базу, где все пароли были бы случайными и длинными. Каждый раз одна картина: 60–70% базы - словарные слова с цифрами на конце, ещё 15–20% - вариации ника, и только оставшиеся 10–15% - действительно стойкие пароли, которые не поддаются крекингу.

Администраторы частных серверов ставят bcrypt и считают вопрос закрытым. Cost factor? Дефолтный. Минимальная длина пароля? Шесть символов. Rate limiting? Отсутствует. Bcrypt в такой конфигурации защищает не пользователя, а самооценку администратора. При этом cost=10 OWASP уже не рекомендует - 0.05 секунды за хэш слишком быстро для 2025 года.

Самый недооценённый риск утечки - не сам взлом хэшей. Это credential stuffing. Геймеры используют одинаковые пароли везде, и полторы тысячи пар из игровой базы превращаются в десятки скомпрометированных Gmail-аккаунтов. Bcrypt - одно звено. Без минимальных требований к паролям, без ограничения попыток входа, без мониторинга запросов к базе - это звено не держит цепь. Проблема не в криптографии. Проблема в том, что админ не потратил 15 минут на конфигурацию. Проверьте свой сервер nmap-ом на открытый 3306 - если он торчит наружу, у вас та же проблема, что и у половины серверов Dragonica в Shodan.
 
Последнее редактирование модератором:
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab