Понимание файлов cookie для WordPress Auth

  1. Вступление недавно опубликованная уязвимость побудил меня еще раз взглянуть на функцию WordPress...
  2. Важность ключей и солей
  3. Защита ваших ключей и солей
  4. Заключение

Вступление

недавно опубликованная уязвимость побудил меня еще раз взглянуть на функцию WordPress wp_validate_auth_cookie, которая отвечает за проверку подлинности пользовательских запросов и в конечном итоге контролирует доступ к вашей установке WordPress. Этот пост не об этой конкретной уязвимости ( больше информации здесь ) а скорее о том, как WordPress генерирует и проверяет файлы cookie аутентификации для авторизации пользовательских запросов. Если вы являетесь пользователем WordPress, я рекомендую вам прочитать дальше, чтобы узнать, что стоит между злоумышленниками и доступом к вашему сайту.

Примечание. Все примеры кода WP относятся к версии 3.9.

WordPress Auth Cookie

Когда пользователь получает доступ к любым ресурсам после аутентификации (Dashboard, управление плагинами, управление пользователями и т. Д.), Его данные аутентификации передаются через cookie-файл аутентификации и проверяются функцией wp_validate_auth_cookie ().

Этот файл cookie состоит из следующих компонентов:

Примечание: | символ (закодированный в% 7C) служит разделителем.

1) идентификатор куки

То, что я называю «идентификатором cookie», определяется в файле default-constants.php:

Это просто объединение «wordpress_» и значения с именем COOKIEHASH, которое также определено в том же файле:

Как видите, COOKIEHASH - это не более чем MD5 URL вашего сайта. Вот подтверждение с использованием URL моего тестового сайта:

2) Имя пользователя

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

3) Срок действия

Значение срока действия - это временная метка UNIX, которая устанавливается при создании файла cookie в wp_set_auth_cookie и по умолчанию составляет 2 дня (определены в pluggable.php).

php)

Вот временная метка по умолчанию, которая была сгенерирована для этого демонстрационного куки.

Вот временная метка по умолчанию, которая была сгенерирована для этого демонстрационного куки

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

4) Хеш

Пока что все компоненты cookie (идентификатор cookie, имя пользователя и срок действия) являются предсказуемыми. Предсказуемость, очевидно, является плохой вещью, когда дело доходит до файла cookie аутентификации, в который входит элемент хеша. Чтобы увидеть, как генерируется этот хеш, мы можем обратиться к функции wp_generate_auth_cookie () из файла pluggable.php, расположенного в wp- включает в себя каталог.

php, расположенного в wp- включает в себя каталог

Как видите, хеш-компонент cookie - это значение md5, состоящее из имени пользователя и срока действия, оба из которых являются предсказуемыми. Чтобы решить эту проблему, функция PHP hash_hmac использует общий секретный ключ. Этот ключ представляет собой хэш имени пользователя (предсказуемый), срока действия (предсказуемый), схемы (предсказуемый, по умолчанию «auth») и pass_frag.

Pass_frag - это 4-х символьная подстрока хэша пароля пользователя (от 8 до 12 символов). Вот pass_frag из моей учетной записи администратора 'test':

Хэш пароля пользователя состоит из наборов символов az, AZ, 0-9 и двух специальных символов - прямой слеш (/) и точка (.). Поскольку длина pass_frag составляет всего 4 символа, общее количество возможных комбинаций (энтропия) составляет (26 + 26 + 10 + 2) 4 = 16 777 216. Это может выглядеть как большое число, но грубое форсирование всех возможных комбинаций довольно тривиально. Следует отметить, что для целей создания и проверки подлинности куки-файла пользователя энтропия, обеспечиваемая паролем пользователя, одинакова, независимо от того, имеет ли этот пользователь пароль из 4 символов или пароль из 40 символов.

Итак, учитывая предсказуемость всех отдельных элементов, составляющих хеш, что делает окончательный хеш (и полученный cookie) непредсказуемым? Ответ лежит в функции wp_hash, используемой для построения ключа (находится в pluggable.php). Давайте взглянем:

Давайте взглянем:

Хотя этой функции не так много, она выполняет один важный шаг для обеспечения непредсказуемости cookie - она ​​солит данные, используя функцию wp_salt. Эта функция создает соль из значений AUTH_KEY и AUTH_SALT, найденных в файле wp-config.php.

php

Эти два значения объединяются вместе и возвращаются в функцию wp_hash () как окончательное солт-значение.

Эти два значения объединяются вместе и возвращаются в функцию wp_hash () как окончательное солт-значение

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

Должно быть очевидно, что, поскольку все элементы cookie, кроме соли, являются предсказуемыми и находятся под контролем конечного пользователя, обязательно, чтобы значения AUTH_KEY и AUTH_SALT были защищены. В 2012 году на Codeseekah написал сообщение в блоге об этой самой проблеме , Давайте еще раз посмотрим на последствия предсказуемости или раскрытия ключа / соли ...

Важность ключей и солей

Когда пользовательский файл cookie передается пользователем, он проверяется функцией wp_validate_auth_cookie () перед предоставлением доступа к запрашивающей стороне. Вот некоторые из ключевых элементов этой функции.

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

Функция также захватывает хэш пароля, связанный с именем пользователя, переданным в cookie (при условии, что он действителен), и извлекает четырехсимвольный код pass_frag. Затем он восстанавливает файл cookie (так же, как wp_set_auth_cookie), создает хэш и сравнивает его с хешем, созданным из файла cookie, переданного пользователем. Пока они совпадают, пользователь проходит аутентификацию и предоставляет доступ к запрошенному ресурсу (при условии, что он авторизован).

Имея это в виду, рассмотрим следующие два момента:

  • Все значения, используемые для восстановления файла cookie аутентификации, кроме ключа / соли из wp-config, находятся под контролем запрашивающего пользователя.
  • В отличие от многих других веб-приложений, WordPress не использует управление сеансами, поэтому проверка подлинности полностью зависит от правильной конструкции файла cookie аутентификации и не требует соответствующего сеанса пользователя.

Это важные моменты, потому что, если раскрываются значения ключа и соли, используемые при создании хеш-части файла cookie, можно создать действительный постоянный файл cookie авторизации для любого пользователя по своему выбору. Чтобы продемонстрировать это влияние раскрытия, я изменил значения auth_key и auth_salt в моем файле wp-config на DisclosedKey и DisclosedSalt соответственно.

Предполагая, что я злоумышленник, имеющий доступ к этим значениям, теперь я могу восстановить действительный файл cookie авторизации для пользователя по своему выбору и получить доступ к установке WordPress. Единственная информация, которую мне еще нужно сгенерировать, это pass_frag целевого пользователя.

Я написал базовый скрипт на python (доступен для скачивания ниже), который может генерировать все возможные комбинации pass_frag и создавать действительный файл cookie WordPress.

Демонстрационный скрипт для генерации всех возможных файлов cookie аутентификации WordPress для данного пользователя с заданным действительным ключом и солт-значением. Демонстрирует важность защиты секретных ключей и солей WP!

MD5: 78d68cd4e4e48869beda1b4f2f75fc6c Языки: английский Автор: Майк Чумак (T_v3rn1x) - @SecuritySift Лицензия: Дата бесплатного пользования : 20 апреля 2014 г.

В демонстрационных целях я сократил общее пространство символов с 16 миллионов до чуть более 50000 (за счет сокращения отдельных наборов символов).

Сценарий генерирует все возможные файлы cookie для аутентификации (используя все 4 комбинации символов pass_frag) для данного пользователя с учетом ключа и соли. Вот пример для администратора:

Вы можете передавать эти значения непосредственно в запросы Burp Intruder и brute force до тех пор, пока не будет обнаружен действительный файл cookie. Обратите внимание, что я сгенерировал сгенерированные куки с числовым идентификатором и соответствующим pass_frag. Простое регулярное выражение для обработки соответствия / замены полезной информации извлечет эту постороннюю информацию из файла cookie перед отправкой ее цели (^ [0-9] *: [0-9a-zA-z \. \ /] {4}:).

Обратите внимание, что в демонстрации 50 000 запросов, приведенных ниже, я обнаружил действительный файл cookie примерно в 1/10 пути к моему файлу (менее чем за 3 минуты, при тестировании с локальной установкой WordPress).

Обратите внимание, что в демонстрации 50 000 запросов, приведенных ниже, я обнаружил действительный файл cookie примерно в 1/10 пути к моему файлу (менее чем за 3 минуты, при тестировании с локальной установкой WordPress)

С известными значениями соли и ключа потребуется не более 16 777 216 миллионов запросов для доступа к учетной записи любого пользователя. Это относится к каждому пользователю этой установки WordPress! Хотя многие установки WordPress будут иметь своего рода защиту от грубой силы от страницы аутентификации, они вряд ли будут иметь такую ​​защиту для всех URL-адресов / страниц, что делает эту атаку грубой силой осуществимой (опять же, предполагая, что секретный ключ и соль известны).

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

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

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

Защита ваших ключей и солей

Когда дело доходит до защиты ваших секретных ключей и солей, Codeseekah сделал несколько хороших рекомендаций некоторые из которых я повторю здесь:

1) Ограничьте доступ к вашему файлу wp-config.php. Только доверенные администраторы должны иметь доступ к этому конфиденциальному файлу. Фактически, доступ к этому файлу также предоставит доступ к вашим учетным данным БД.

2) Поддерживайте актуальность установки WordPress (включая все плагины), чтобы предотвратить раскрытие на основе эксплойтов или несанкционированный доступ.

3) Подумайте о том, чтобы периодически менять ключи и соли. Имейте в виду, что это потребует от всех пользователей повторной аутентификации, что может быть эффективным способом прекращения доступа, если вы подозреваете компромисс. Здесь есть API для генерации псевдослучайных солей / ключей: https://api.wordpress.org/secret-key/1.1/salt/ , Вам не нужно использовать автоматический генератор, но что бы вы ни делали, не меняйте их на более слабые значения и не уменьшайте энтропию!

4) Если вы чувствуете, что одной соли недостаточно, вы можете объединить другое значение с концом соли, созданной с помощью функции wp_hash () (например, salt = wp_salt ($ схема). 'UNIQUE_VALUE';). Это увеличит энтропию и будет означать, что компонент вашей соли будет определяться в двух файлах конфигурации WordPress, а не в одном.

5) Используя ту же технику, что и выше, вы также можете уменьшить предсказуемость других компонентов вашего файла cookie для аутентификации. Например, добавьте еще один параметр при создании хэша MD5 для части идентификатора файла cookie COOKIEHASH (например, define ('COOKIEHASH', md5 ($ siteurl. 'UNIQUE_VALUE'))));

Важно: не забудьте сделать резервную копию вашей установки WordPress, прежде чем вносить какие-либо изменения в конфигурационные файлы!

Заключение

Моим намерением для этого поста было продемонстрировать две вещи:

1) Как WordPress использует куки аутентификации для проверки пользовательского запроса вместо традиционного управления сессиями.

2) Важность защиты ваших секретных ключей и солей.

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

Обратите внимание, что я не предполагаю, что в этой реализации аутентификации на основе файлов cookie WordPress есть уязвимость, которую можно использовать. Хотя подход, основанный на сеансах, безусловно, сократит срок службы файла cookie аутентификации и потенциальную уязвимость учетной записи пользователя, этот подход является правильным решением, если вы храните свои ключи и секреты в секрете!

Как всегда, спасибо за чтение. Обратная связь приветствуется. - Майк

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