open atlas
↑ К треку
Наступательная безопасность RED · 03 · 03

Атаки на пароли и их взлом

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

RED Middle ◷ 15 min
Уровень
ОсновыJuniorMiddleSenior

На авторизованном задании тестировщик выгружает таблицу users из лабораторной базы и смотрит на колонку хешей паролей. Пока ничего не расшифровано — хеш односторонний, красть нечего, ключа нет. И всё же в течение часа рядом с третью аккаунтов появляются открытые пароли. Не потому, что тестировщик сломал математику, а потому, что он арендовал GPU-стенд, а приложение хранило пароли как чистый SHA-256. На таком железе одна карта перебирает миллиарды кандидатов SHA-256 в секунду; весь словарь RockYou из четырнадцати миллионов утёкших паролей заканчивается за доли секунды, а полный перебор всех 8-символьных строк из строчных букв завершается до обеда. Парольная политика защитника перестала что-либо значить после утечки дампа. Значение имело одно проектное решение, принятое много лет назад: какая функция превратила пароль в этот хеш и была ли соль. Этот урок — вскрытие того решения.

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

Сначала авторизация: это вскрытие глазами защитника

Всё ниже предполагает подписанное задание с явно определённым скоупом — заведомо уязвимую лабораторию, CTF, дамп хешей из вашей собственной системы или цель внутри программы bug bounty. Запуск взломщика против учётных данных, которые вы не имели права получать, — это несанкционированный доступ в большинстве юрисдикций, а «я просто хотел посмотреть, насколько они слабые» — не оправдание. Мы изучаем экономику атакующего по одной причине: нельзя оценить стоимость контроля, которого не понимаешь. Сам вопрос «достаточно ли bcrypt?» неразрешим, пока вы не умеете прикинуть, сколько догадок в секунду стоит ваш хеш атакующему и сколько их ему нужно. Читайте это как вскрытие, которое защитник проводит над собственным хранилищем учёток, — учитесь видеть колонку хешей так, как её видит взломщик, чтобы work factor был верным до того, как дамп когда-либо утечёт. Никаких готовых рецептов взлома здесь — только механизм и его числа.

Онлайн против офлайна: две совершенно разные игры

Есть две арены, и по сложности они не близки. Онлайн-атака подбирает пароли против живой системы — отправляя их в форму входа, в API, на SSH-демон. Здесь часами управляет защитник: rate limiting, блокировка аккаунта, экспоненциальная задержка и CAPTCHA ограничивают атакующего парой догадок в секунду на аккаунт, и каждая догадка видна в логах. Онлайн-подбор по замыслу медленный и шумный — поэтому доминирующая онлайн-атака сегодня вовсе не слепой перебор, а credential stuffing: повтор пар логин-пароль, уже утёкших из других пробоев, в расчёте на переиспользование. Эта ставка играет, потому что люди переиспользуют пароли; защита — это MFA и проверка по базам утёкших паролей, а не более быстрый хеш.

Офлайн-атака — совсем другая игра. Как только атакующий держит хеши — из дампа SQL-инъекции, украденного бэкапа, скомпрометированной реплики, — между ним и ответом больше нет формы входа. Он вычисляет хеши кандидатов на собственном железе, настолько быстро, насколько позволяет кремний, без rate limit, без блокировок и без единой записи в ваших логах. Защитник потерял контроль над временем; единственный оставшийся рычаг — насколько дорого обходится вычисление одного хеша. В этом весь стержень урока: онлайн-безопасность — про скорость; офлайн-безопасность — про стоимость одного хеша. Пароль из 12 символов за быстрым хешем тривиально взламывается офлайн и абсолютно безопасен онлайн — тот же пароль, противоположный исход, потому что у этих игр разная физика.

Экономика: догадки в секунду умножить на стоимость хеша

Офлайн-взлом сводится к одному неравенству, которое атакующий держит в голове: смогу ли я позволить себе достаточно догадок, чтобы покрыть вероятное пространство ключей раньше, чем данные перестанут стоить усилий? Два члена — это скорость (сколько хешей кандидатов в секунду считает железо) и пространство ключей (сколько кандидатов придётся перебрать). Защитник не может сжать пространство ключей — это пароль пользователя, — поэтому вся защитная игра сводится к обрушению скорости, а скорость задаётся почти целиком тем, какую хеш-функцию вы выбрали.

Числа жестокие, и их стоит усвоить. Современный GPU считает порядка десятков миллиардов догадок быстрого хеша в секунду для одного MD5 или SHA-256, а арендованный многокарточный стенд умножает это. Против такой скорости быстрый хеш — вообще не защита: весь список RockYou исчерпывается заметно меньше чем за секунду, а исчерпывающий перебор прогрызает короткие пространства ключей за минуты. Защита — выбрать намеренно медленный парольный хеш: bcrypt, scrypt, Argon2, специально сделанный дорогим. Против bcrypt с реалистичным cost factor тот же GPU падает с десятков миллиардов до нескольких десятков тысяч догадок в секунду — замедление примерно в миллион раз. Словарь, который раньше исчерпывался за долю секунды, теперь занимает часы; исчерпывающий перебор, заканчивавшийся до обеда, теперь переживает ценность данных. В пароле ничего не изменилось — изменилась только стоимость одного хеша, и один этот фактор сдвинул атаку с тривиальной на нерентабельную.

Хеш-функцияСоздана дляДогадок/сек на GPU (порядок)Офлайн-вердикт
MD5 / SHA-1 / SHA-256Скорость (целостность файлов, не пароли)~1010–1011Дамп ≈ бесплатный словарь; не использовать для паролей
bcrypt (cost 12)Медленность, настраиваемый work factor~104~106× медленнее; словарь теперь занимает часы
scrypt / Argon2idМедленность + memory-hardness~103–104Стоимостью RAM бьёт и по дешёвому параллелизму GPU/ASIC

Соль: почему случайное значение на пользователя убивает предвычисление

Work factor замедляет вычисление одного хеша; соль ломает способность атакующего амортизировать работу по множеству хешей. Соль — это уникальное случайное значение, хранимое рядом с каждым хешем и подмешиваемое во вход перед хешированием, так что два пользователя с одинаковым паролем Summer2024! получают два совершенно разных хеша. Одно это свойство разрушает сразу три экономики атакующего. Во-первых, оно убивает rainbow-таблицы — гигантские предвычисленные таблицы соответствия, отображающие хеши обратно в открытый текст: rainbow-таблица строится для несолёных хешей, а соль на пользователя означала бы, что атакующему нужна отдельная таблица под каждую соль, что вычислительно абсурдно, — и предвычисление схлопывается обратно в живой перебор. Во-вторых, оно убивает дедупликацию хешей: в несолёном дампе все аккаунты с самым популярным в мире паролем делят один хеш, так что взломав его однажды, взламываешь их все; соль заставляет атаковать каждый хеш по отдельности. В-третьих, она убирает мгновенный сигнал о том, что два пользователя делят пароль.

Ключевой нюанс для зрелого инженера: соль не секретна и не должна быть секретной. Она хранится в открытом виде прямо рядом с хешем, и это нормально — её задача в уникальности, а не в конфиденциальности. Соль никак не замедляет взлом одного конкретного хеша; если атакующему нужен пароль одного определённого пользователя, соль защитнику вообще не помогает. Вся ценность соли — на масштабе: она превращает «взломай дамп однажды — разблокируй всех» в «взламывай каждый аккаунт с нуля, по одному», что в сочетании с медленным work factor и делает дамп всей базы экономически безнадёжным. Современные парольные хеши (bcrypt, Argon2) генерируют и встраивают соль за вас — именно поэтому нельзя городить это вручную на голом быстром хеше.

Почему это работает

Почему GPU-железо так разрушительно именно против быстрых хешей и почему Argon2 добавляет стойкость по памяти поверх медленности? Быстрый хеш вроде SHA-256 — это крошечная безсостоянийная арифметика, ровно та нагрузка, что тысячи мелких ядер GPU гонят в массовом параллелизме, а ASIC вшивает в кремний ещё дешевле. Чистая медленность (cost factor у bcrypt) помогает, но более богатый атакующий всё равно может бросить на задачу больше ядер. Стойкость по памяти снова меняет экономику: Argon2id и scrypt заставляют каждый хеш выделять крупный блок RAM, а RAM дорого тиражировать по тысячам параллельных ядер или класть на ASIC. Так стоимость памяти ограничивает, насколько атакующий может распараллелиться, и притупляет преимущество GPU/ASIC, которое чистая вычислительная медленность оставляет открытым. Поэтому текущие рекомендации тянутся в первую очередь к Argon2id, с bcrypt как хорошо изученной запасной опцией.

Как защитник оценивает стоимость контроля

Сложите детали — и задача защитника в том, чтобы офлайн-взлом стоил дороже, чем стоят данные. Это три решения по порядку. Выбрать медленный, стойкий по памяти парольный хеш (Argon2id или bcrypt/scrypt) — никогда голый быстрый хеш, никогда шифрование (шифрование обратимо; вам нужна односторонность). Настроить work factor до наибольшей стоимости, какую терпит ваш бюджет задержки входа — ориентировочно стремясь к доле секунды на хеш на собственном железе, — и пересматривать его по мере ускорения железа, потому что cost factor, выбранный в 2015-м, сегодня слишком дёшев. Полагаться на автоматическую соль на пользователя из библиотеки, чтобы один взлом никогда не обобщался на всю базу. И принять, что хеширование — последний рубеж, а не единственный: ограничьте онлайн-игру через rate limiting, блокировки и MFA, а новые пароли проверяйте по базам известных утечек, чтобы credential stuffing нечего было повторять. Зрелый рефлекс тот же, что и везде в безопасности: считайте, что дамп рано или поздно утечёт, и убедитесь, что контроль уже оценён так, что, когда это случится, арифметика атакующего не сходится.

Выбери лучший вариант

Вы упрочняете хранилище учётных данных перед запуском. Текущий дизайн хранит пароли как чистый SHA-256. На авторизованном ревью вы подтвердили, что один GPU взломал бы большую часть утёкшего дампа меньше чем за час. Выберите изменение, которое действительно закрывает офлайн-экспозицию.

Викторина

Один и тот же 12-символьный пароль абсолютно безопасен против онлайн-атаки на форму входа, но тривиально взламывается, как только утекает дамп хешей (при условии быстрого хеша). Почему исходы противоположны?

Викторина

Ревьюер говорит: «мы добавили соль на пользователя, так что наше хранилище паролей на SHA-256 теперь безопасно против офлайн-взлома». Что не так с этим утверждением?

Расставь шаги по порядку

Упорядочьте шаги кампании офлайн-взлома против дампа с быстрым несолёным хешем, от получения до результата:

  1. 1 Атакующий получает дамп хешей (SQLi, украденный бэкап, скомпрометированная реплика)
  2. 2 Определяет хеш-функцию и подтверждает, что она быстрая и несолёная
  3. 3 Прогоняет словарь (например, RockYou) частых/утёкших паролей на GPU-железе
  4. 4 Откатывается на масочный перебор по оставшемуся короткому пространству ключей
  5. 5 Восстанавливает открытый текст для большой доли аккаунтов и пробует их в других местах (stuffing)
Вспомните перед уходом
  1. 01
    Объясните, почему онлайн- и офлайн-атаки на пароли — совершенно разные игры, и какой единственный рычаг есть у защитника против офлайн-взлома.
  2. 02
    Пройдите по экономике офлайн-взлома и объясните, как work factor и соль по отдельности меняют арифметику атакующего — и почему одно без другого недостаточно.
Итог

Взлом паролей — это задача экономики, и зрелое прозрение в том, что единственный офлайн-рычаг защитника — стоимость одного хеша. Онлайн и офлайн — разные игры с разной физикой: онлайн защитник управляет временем через rate limiting, блокировки и MFA, поэтому живая угроза — это credential stuffing (переиспользованные пары из других пробоев), а не слепой подбор; офлайн атакующий держит дамп и считает догадки на своём железе без rate limit, без блокировок и без логов. Против быстрого несолёного хеша (MD5/SHA-256) один GPU идёт на десятках миллиардов догадок в секунду, так что дамп фактически бесплатный словарь — весь список RockYou исчерпывается меньше чем за секунду. Фикс — два ортогональных рычага: намеренно медленный, стойкий по памяти хеш (Argon2id, bcrypt, scrypt), режущий скорость атакующего в ~10^6 раз, плюс автоматическая соль на пользователя, убивающая rainbow-таблицы и межаккаунтную дедупликацию, чтобы один взлом никогда не обобщался. По отдельности ни одного не хватит — соль без медленности оставляет каждый хеш перебираемым, медленность без соли снова включает предвычисление, — а политика длины или утекаемый pepper им не замена. Теперь, читая хранилище учёток, вы задаёте тот же первый вопрос: сколько догадок в секунду стоит этот хеш атакующему, который уже держит дамп?

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 6 завершено
Связанные уроки

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.