Безопасность: Тотальная защита паролей в базах данных.

Discussion in 'Безопасность и Анонимность' started by -=Cerberus=-, 13 Nov 2013.

  1. -=Cerberus=-

    -=Cerberus=- κρυπτός γράφω

    Joined:
    29 Apr 2012
    Messages:
    1,321
    Likes Received:
    930
    Reputations:
    391
    Всем привет!
    Поговорим мы сегодня о защите паролей пользователей и администраторов от взлома, а точнее о максимальном усложнении этого процесса для взломщика.

    На сегодняшний день вычислительные мощности позволяют угадывать очень сложные пароли пользователей, не говоря уже, о простых паролях. Скорости перебора для простых алгоритмов хеширования давно перевалили за отметку в 20-50 миллиардов паролей в секунду!
    Здесь можно посмотреть сравнительные тесты: LINK , но это далеко не предел и существуют вычислительные кластеры насчитывающие до 25 видеокарт на борту каждой из них по 2048 вычислительных ядер
    (51 200 ядер).

    На мой взгляд, в области хранения паролей существуют три фундаментальные проблемы:

    1. – отсутствие строгих правил на создание пароля (использование разных регистров букв, цифр и знаков, ограничение длинны пароля).
    2. – использование слабых алгоритмов хеширования(тут скрыта также проблема в том, что если использовать сильные алгоритмы хеширования можно с легкостью получить высокую нагрузку на систему)
    3. – человеческий фактор.

    Заметка: Сразу оговорюсь, что мы будем использовать сильный алгоритм хеширования: bcrypt(Blowfish).

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

    Заметка: В данной статье не будет представлена реализация. Описан лишь сам процесс.

    По(на)ехали!

    Описание системы:
    1. При регистрации пользователя будем выдавать ему случайный PIN код. Пример: 6740
    2. Введем ограничения на сложность пароля.
      • len(password) >= 9 && len(password) =< 20
      • password содержит буквы в верхнем и нижнем регистре, цифры, символы
      • Набор используемых символов равен минимум 7. Пример пароля, который не удовлетворяет этим требованиям: Pas$121121 (причина: набор используемого алфавита равен 6) Пример правильного пароля: pA$w0orD!@

    Итак, наш «горе» пользователь изобрел сложный пароль, записал PIN код и готов к своему первому входу на сайт.
    PIN: 6740 PASSWORD: pA$w0orD!@

    Посмотрим, что будет твориться внутри скрипта авторизации пользователя.

    Форму авторизации мы защитим капчей (правда она не всегда спасает):
    1. – ввод username (email для входа использовать мы не будет, это не отвечает нашим запросам к безопасности пользователя)
    2. – PIN код
    3. – капча

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

    Но на этом мы не ослабляем уровень недоверия к пользователю, предположим, что это хакер который решил испортить нашу систему, через высокую нагрузку на серверный процессор(такое возможно, и об этом можно прочитать в недавней уязвимости в ColdFusion). По сути создается ситуация когда враг внутри и у него есть все необходимые данные для входа и он может постоянно логинясь нагрузить процессор(напоминаю используем в алгоритме хэширования bcrypt).
    Избавимся от данной проблемы, создав механихм тайм-аутов на релогин пользователя, скажем 10 минут.
    Вариант два это утечка PIN кода или username пользователя, с последующим подбором PIN кода. Тогда может последовать брутфорс пароля, который опять таки может привести к высокой нагрузке на сервер.
    Защита от подобной ситуации – это ограниченное время жизни токена полученного при прохождении первого этапа авторизации и внутренняя проверка входного пароля.
    Тут следует посмотреть на сам алгоритм хранения и создания хэша пароля пользователя (дальше будет рассмотрен 3 вариант компрометации системы когда хакер получил доступ в базу данных к примеру через SQL инжект).

    1. Пароль на входе pA$w0orD!@
    2. После проверки на правила применяемые к паролям. Он объединяется с некой константой, которая хранится в скрипте(что еще на один уровень повысит защищенность пароля) 0d*&d@/d@s-1. pA$w0orD!@ Получаем: 0d*&d@/d@s-1pA$w0orD!@
    3. К полученной строке применяется функция хеширования bcrypt(0d*&d@/d@s-1paS$word)
    4. Получаем хеш $2a$05$AOdUs4M6vtlBJzadn.t5SUWM1SS.5hfUL64G

      Заметка: Функция хеширования алгоритмом bcrypt будет немного изменена и значение соли AOdUs будет не совсем случайным, первый символ в ней это второй символ пароля. Сейчас объясню для чего подобное раскрытие второго символа в пароле пользователя. Этот символ мы будем использовать на этапе проверки пароля, до того момента, когда скрипт будет рассчитывать полный хеш от всего пароля целиком. Тем самым мы исключаем еще одну возможность нагрузить сервер, хотя опять таки мы не гарантированы оттого, что наш пользователь не инсайдер. В любом случае проблему можно решить ограничением неудачных попыток входа пользователя.
    5. Отбросим $2a$05$, отдельно запишем соль AOdUs, а от остатка s4M6vtlBJzadn.t5SUWM1SS.5hfUL64G посчитаем MD5 хеш.
      MD5(s4M6vtlBJzadn.t5SUWM1SS.5hfUL64G) == 17004c8884f432d0c46d2f4e6b2c2a77
    6. В базу мы запишем PIN:HASH:SALT и другие данные пользователя.
      6740:17004c8884f432d0c46d2f4e6b2c2a77:AOdUs

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

    Этап проверки пароля это те же действия по его созданию за исключением проверки второго символа пароля, который записан первым символом в поле SALT. Его мы проверим до расчета хеша от полного пароля простым сравнением.

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

    P.S. Статья получилась сложная и далеко не для новичков в области криптографии, но думаю, основную идею должны были понять все.
    Некоторые вещи я просто опускал и не стал описывать подробно.

    Спасибо за внимание!
     
    nynenado, ibeworkin, nina1987 and 9 others like this.