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


Вместе с тем, мы также придаем большое значение портативности, то есть возможности загружать и выгружать данные из Discourse по собственному желанию. Именно поэтому Discourse, в отличие от прочих сервисов форумов, подпадает под лицензию Creative Commons. Даже обычный пользователь на Discourse может свободно экспортировать и скачивать свои посты прямо из личного профиля.

Владельцы форумов имеют возможность создавать бэкапы и восстанавливать целые базы данных сайтов прямо из администраторской панели в веб-браузере. Автоматические бэкапы по умолчанию производятся на еженедельной основе. Я же не просто так считаюсь ведущим мировым экспертом по бэкапам!


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

Чтобы устранить эту опасность, мы постепенно ужестчали требования к созданию бэкапов на Discourse разными способами:

  • Пароль администратора должен содержать не менее 15 символов;
  • Такие действия администратора, как создание или закачка бэкапа, официально заносятся в логи;
  • Ключи для скачивания бэкапа одноразовые и отсылаются на почту администратора, чтобы удостовериться, что у него действительно есть доступ к этому адресу.

Информационная безопасность завязана на защите в глубину, так что все эти строгости помогают… но нам все равно нужно представить себе, что какие-нибудь интернет-злодеи завладели вашей базой данных. И что теперь? Ну, сначала разберемся, что в ней вообще есть.

1. Куки

Именно куки позволяют браузеру идентифицировать пользователя. Обычно они хранятся в виде хэшей, а не конкретных значений — следовательно, даже получив доступ к хэшу, невозможно выдавать себя за конечного пользователя. Более того, во многих современных веб-фреймворках жизненный цикл куков невелик, так что они в любом случае остаются актуальными не более 10-15 минут.

2. E-mail адреса

Конечно, для пользователей тот факт, что их e-mail попал в руки к хакерам — повод для волнения, но на деле в наше время мало кто так уж трепетно относится к своим адресам.

3. Все посты и содержимое веток

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

4. Хэши паролей

Все, что остается — это хэши паролей. И это… это действительно серьезная проблема.

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

Именно по этой причине, если вы узнали (или даже просто заподозрили), что ваша база данных попала в чужие руки, первое, что вы должны сделать — поменять пароли всех пользователей.


А что, если не узнали? Стоит ли действовать на опережение и менять всем пароли раз в 30 дней, следуя примеру худших IT отделений мегакорпораций в мире? Это сильно портит пользовательский опыт, и само по себе может привести к патологиям. В реальности велика вероятность того, что вы не узнаете об утечке данных, пока не будет уже слишком поздно что-то предпринимать. Поэтому принципиально важно замедлить процесс для хакеров, отвоевать себе какое-то время, чтобы успеть среагировать и разобраться с ситуацией.

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

  1. Алгоритм хэширования. Он должен быть максимально медленным и, в идеале, рассчитанным на то, чтобы еще замедляться на графических процессорах. Почему — вы ясно увидите абзацев через пять.
  2. Рабочий фактор или количество итераций. Чем больше, тем лучше, единственное ограничение — возможность DoS атаки.

Я читал руководства, в которых говорилось, что общий рабочий фактор следует делать настолько высоким, чтобы хэширование паролей занимало как минимум 8 миллисекунд на соответствующей платформе. Как выясняется, Sam Saffron, один из сооснователей Discourse наряду со мной, принял верное решение в далеком 2013 году, выбрав, по рекомендации NIST, PBKDF2-HMAC-SHA256 и PBKDF2-HMAC-SHA256 и 64 тысячи итераций. Мы произвели замеры и выяснили, что и в самом деле, процесс занимает около 8 миллисекунд с применением нашего нынешнего кода для входа в систему на Ruby на использующихся серверах (весьма неплохих, Skylake 4.0 Ghz).

Но это было четыре года назад. Насколько надежны хэши паролей в нашей базе данных на сегодняшний день? А что будет еще через четыре года? Через десять лет? Мы создаем программу с заделом на будущее и хотим быть уверены, что принимаем верные решения, которые впоследствии послужат ко всеобщей безопасности. Поэтому в соответствии с принципом «проектируй с расчетом на злоумышленников» пришло время надеть шлем Дарт Вейдера и вжиться в роль злодея — давайте взломаем свои собственные хэши!


Для этого мы будем использовать наикрутейший графический процессор, известный на сегодняшний день — GTX 1080 Ti. Для справки: на 1080 PBKDF2-HMAC-SHA256 достигает 1180 kH/s, а на 1080 Ti — 1640 kH/s. Всего за одно поколение видеокарты возможности для атаки на хэши возросли почти на 40%. Вдумайтесь в эти цифры.

Для начала небольшой тест в духе hello world, чтобы убедиться, что все работает. Я скачал hashcat, зашел на демо-версию нашего сайта на try.discourse.org и создал там новый аккаунт с паролем 0234567890. Проверил базу данных и увидел, что для нового пользователя в базе данных сгенерировались следующие значения для колонок hash и salt:

hash
93LlpbKZKficWfV9jjQNOSp39MT0pDPtYx7/gBLl5jw=
salt
ZWVhZWQ4YjZmODU4Mzc0M2E2ZDRlNjBkNjY3YzE2ODA=


Hashcat требует следующего формата входного файла: на каждый хэш отводится одна строка, которая содержит тип хэша, число итераций, salt и hash (закодированные в base64); все это разделяется двоеточиями:

type iter salt hash
sha256:64000:ZWVhZWQ4YjZmODU4Mzc0M2E2ZDRlNjBkNjY3YzE2ODA=:93LlpbKZKficWfV9jjQNOSp39MT0pDPtYx7/gBLl5jw=


Давайте забьем все это в hashcat и посмотрим, что получится:

type iter salt hash
sha256:64000:ZWVhZWQ4YjZmODU4Mzc0M2E2ZDRlNjBkNjY3YzE2ODA=:93LlpbKZKficWfV9jjQNOSp39MT0pDPtYx7/gBLl5jw=


Замечу, что мы задаем умышленно маленький объем работы — нужно угадать всего-то три символа. Само собой, много времени это не заняло! Видите пароль в самом конце? Мы сделали это.

sha256:64000:ZWVhZWQ4YjZmODU4Mzc0M2E2ZDRlNjBkNjY3YzE2ODA=:93LlpbKZKficWfV9jjQNOSp39MT0pDPtYx7/gBLl5jw=:0234567890

Теперь мы убедились, что все работает, и можно браться за дело. Пойдем от простого к сложному. Сколько понадобится времени, чтобы методом полного перебора хакнуть простейший из возможных паролей на Discourse, состоящий из 8 цифр — а это всего-то навсего 108, то есть чуть больше сотни миллионов разных комбинаций?

Hash.Type........: PBKDF2-HMAC-SHA256
Time.Estimated...: Fri Jun 02 00:15:37 2017 (1 hour, 0 mins)
Guess.Mask.......: ?d?d?d?d?d?d?d?d [8]


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

?d?d?d?d?d?d?d?d?d [9]
Fri Jun 02 10:34:42 2017 (11 hours, 18 mins)

?d?d?d?d?d?d?d?d?d?d [10]
Tue Jun 06 17:25:19 2017 (4 days, 18 hours)

?d?d?d?d?d?d?d?d?d?d?d [11]
Mon Jul 17 23:26:06 2017 (46 days, 0 hours)

?d?d?d?d?d?d?d?d?d?d?d?d [12]
Tue Jul 31 23:58:30 2018 (1 year, 60 days)


Но пароли из одних цифр — это же примитив для малышни! Что если взять настоящие пароли, в которых есть по крайней мере строчные буквы, а то и сочетание цифры + заглавные буквы + строчные буквы?

Guess.Mask.......: ?l?l?l?l?l?l?l?l [8]
Time.Estimated...: Mon Sep 04 10:06:00 2017 (94 days, 10 hours)

Guess.Mask.......: ?1?1?1?1?1?1?1?1 [8] (-1 = ?l?u?d)
Time.Estimated...: Sun Aug 02 09:29:48 2020 (3 years, 61 days)


Метод грубой силы «давайте попробуем все возможные сочетания букв и цифр» что-то уже не кажется такой уж блестящей идеей, даже с качественным графическим процессором. Но что если мы сократим этот срок в восемь раз, просто вставив восемь видеокарт в одну машину? Бюджет небольшой компании или состоятельного индивида вполне может это потянуть. К сожалению, когда срок обработки — 38 месяцев, уменьшение в восемь раз погоды не сделает. Давайте лучше представим себе атаку со стороны властей, у которых хватит средств, чтобы бросить на эту задачу несколько тысяч (сокращая срок до 1.1 дня), а то и десятков тысяч (сокращая срок до 2.7 часов) графических процессоров. В таком случае… да. Даже если допустить, что минимальная длина пароля установлена в десять символов, у вас крупные неприятности.


Если мы хотим, чтобы Discourse мог выстоять против правительственных атак, надо придумать что-то. У Hashcat есть удобный режим бенчмарка; вот список самых надежных хэшей из известных ему (то есть, на которые уходит больше всего времени), которые тестировались на графических процессорах 8 Nvidia GTX 1080. Из того, что я опознал, больше всего заслуживают упоминания bcrypt, scrypt и PBKDF2-HMAC-SHA512.

Результаты, который дал этот небольшой эксперимент с hashcat, убедили меня, что в организации хранения хэшей в базе данных мы не допустили грубых ошибок. Но мне хотелось быть абсолютно в этом уверенным, поэтому я обратился к услугам специалиста по безопасности и тестированию на проникновение, чтобы он (предварительно подписав соглашение о неразглашении) попытался взломать два наших рабочих и очень популярных форума на Discourse.

«Мне были предоставлены два набора хэшей паролей из двух разных сообществ на Discourse, которые содержали 5,909 и 6,088 соответственно. В обоих использовался алгоритм PBKDF2-HMAC-SHA256 с рабочим фактором в 64k. При помощи hashcat, моя машина модели Nvidia GTX 1080 Ti GPU генерировала хэши со скоростью ~27,000 в секунду.

К паролям всех сообществ на Discourse применяется один и тот же список требований:

  • Пароль пользователя должен иметь длину не менее 10 символов.
  • Пароль администратора должен иметь длину не менее 15 символов.
  • Пользователи могут выбирать из двух методов идентификации: ввод имени и пароля или вход в систему через сторонние сервисы (Google, Facebook, Twitter и так далее). Если они выбирают второй вариант, система автоматически создает для аккаунта надежный пароль в 32 символа. Определить, был ли пароль задан человеком или сгенерирован автоматически, невозможно.

С использованием списков популярных паролей и масок за три недели мне удалось взломать 39 из 11,997 хэшей, 25 из сообщества -------- и 14 из сообщества --------».

Этот специалист по информационной безопасности регулярно проводит аудиты такого рода, поэтому вместо методов грубой силы он использовал wordlist-ы наряду с эффективными паттернами и масками, которые знал по предыдущим попыткам взлома паролей. В итоге он получил следующий список паролей (один оказался дубликатом):

007007bond
123password
1qaz2wsx3e
A3eilm2s2y
Alexander12
alexander18
belladonna2
Charlie123
Chocolate1
christopher8
Elizabeth1
Enterprise01
Freedom123
greengrass123
hellothere01
I123456789
Iamawesome
khristopher
l1ghthouse
l3tm3innow
Neversaynever
password1235
pittsburgh1
Playstation2
Playstation3
Qwerty1234
Qwertyuiop1
qwertyuiop1234567890
Spartan117
springfield0
Starcraft2
strawberry1
Summertime
Testing123
testing1234
thecakeisalie02
Thirteen13
Welcome123


Если вложить в 8 раз больше ресурсов и удвоить затраченное время, можно допустить, что какой-нибудь хакер, который крайне предан делу или располагает хорошим набором wordlist-ов и масок, в конечном итоге сумеет вычислить 39 х 16 = 624 пароля, то есть около 5% от общего числа пользователей. Это приемлемо, но больше, чем хотелось бы. Мы твердо намерены добавить типы в хеш-таблицу в будущие версии Discourse, чтобы через год-два переключиться на еще более надежную (иными словами, более медленную) схему хэширования паролей.

Это упражнение дало мне более глубокое понимание того, что может произойти при худшем варианте развития событий — утечке базы данных в сочетании с профессиональной атакой на хэши паролей. Теперь я могу с большей уверенностью рекомендовать наш сервис и поручиться за качество той работы, которую наш инженеры проделали, чтобы сделать его безопасным для всех. Так что если вы, как и я, испытываете сомнения, все ли у вас соответствует требованиям безопасности, значит пора проверить это предположение. Не ждите, пока вас взломают — хакер, хакни себя сам!
Поделиться с друзьями
-->

Комментарии (1)


  1. vesper-bot
    06.06.2017 14:43

    Только на картинке не Дарт Вейдер, а Лорд Шлем из "Космобольцев". Неужели и хакеры такие же? :)