Spec-Zone.ru › MySQL 5.7

6.1.2.4 Хеширование паролей в MySQL

Примечание

Информация в этом разделе полностью применима только до MySQL 5.7.5 и только для учетных записей, использующих плагины аутентификации mysql_native_password или mysql_old_password. Поддержка хэшей паролей версии до 4.1 была удалена в MySQL 5.7.5. Это включает удаление плагина аутентификации mysql_old_password и функции OLD_PASSWORD(). Также, secure_auth нельзя отключить, и old_passwords нельзя установить в 1.

Начиная с MySQL 5.7.5, актуальной остается только информация о хэшах паролей версии 4.1 и плагине аутентификации mysql_native_password.

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

MySQL использует пароли в двух фазах взаимодействия клиент-сервер:

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

  • После подключения клиента, он (если имеет достаточные привилегии) может установить или изменить хэш пароля для учетных записей, перечисленных в таблице user. Для этого клиент может использовать функцию PASSWORD() для генерации хэша пароля или использовать оператор генерации пароля (CREATE USER, GRANT или SET PASSWORD).

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

Методы хэширования паролей в MySQL имеют описанную ниже историю. Эти изменения отражены в результатах функции PASSWORD(), которая вычисляет хэши паролей, и в структуре таблицы user, где хранятся пароли.

Исходный (до 4.1) метод хэширования

Исходный метод хэширования создавал строку длиной 16 байт. Такие хэши выглядят так:

mysql> SELECT PASSWORD('mypass');
+--------------------+
| PASSWORD('mypass') |
+--------------------+
| 6f8c114b58f2ce9e   |
+--------------------+

Для хранения паролей учетных записей столбец Password таблицы user на этом этапе имел длину 16 байт.

Метод хэширования 4.1

MySQL 4.1 ввёл метод хэширования паролей, обеспечивающий лучшую безопасность и снижающий риск перехвата паролей. Эта смена включала в себя несколько аспектов:

  • Разный формат значений паролей, генерируемых функцией PASSWORD()

  • Увеличение длины столбца Password

  • Управление по умолчанию методом хэширования

  • Управление допустимыми методами хэширования для клиентов, пытающихся подключиться к серверу

Изменения в MySQL 4.1 произошли в два этапа:

  • MySQL 4.1.0 использовал предварительную версию метода хэширования 4.1. Этот метод существовал недолго, и последующее обсуждение ничего более о нём не говорит.

  • В MySQL 4.1.1 метод хэширования был изменён для создания хэша пароля большей длины - 41 байт:

    mysql> SELECT PASSWORD('mypass');
    +-------------------------------------------+
    | PASSWORD('mypass')                        |
    +-------------------------------------------+
    | *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |
    +-------------------------------------------+
    

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

    Для размещения более длинных хэшей паролей столбец Password в таблице user на этом этапе был изменён на текущую длину - 41 байт.

    Расширенный столбец Password может хранить хэши паролей как в формате до 4.1, так и в формате 4.1. Формат данного значения хэша можно определить двумя способами:

    • Длина: хэши 4.1 и до 4.1 имеют длину 41 и 16 байт соответственно.

    • Хэши паролей в формате 4.1 всегда начинаются с символа *, тогда как пароли в формате до 4.1 никогда не начинаются с него.

    Для явного создания хэшей паролей до 4.1 были внесены два дополнительных изменения:

    • Добавлена функция OLD_PASSWORD(), которая возвращает значения хэшей в формате 16 байт.

    • Для совместимости добавленная системная переменная old_passwords даёт администраторам баз данных и приложениям контроль над методом хэширования. Значение по умолчанию old_passwords 0 приводит к использованию метода 4.1 (41-байтовые хэши), но установка old_passwords=1 приводит к использованию метода до 4.1. В этом случае, PASSWORD() генерирует значения длиной 16 байт и эквивалентно OLD_PASSWORD()

    Для обеспечения контроля администраторами баз данных над тем, как клиенты разрешены для подключения, была добавлена системная переменная secure_auth. Запуск сервера с этой переменной отключённой или включённой разрешает или запрещает клиентам подключаться с использованием более старого метода хэширования паролей до 4.1. До MySQL 5.6.5, secure_auth отключена по умолчанию. Начиная с 5.6.5, secure_auth включена по умолчанию, чтобы обеспечить более безопасную конфигурацию по умолчанию. Администраторы могут отключить её по своему усмотрению, но это не рекомендуется, а хэши паролей до 4.1 устарели и следует избегать их использования. (Инструкции по обновлению учетных записей см. в разделе 6.4.1.3 «Переход от хэширования паролей до 4.1 и плагина mysql_old_password».)

    Кроме того, клиент mysql поддерживает параметр --secure-auth, аналогичный secure_auth, но со стороны клиента. Его можно использовать для предотвращения подключений к менее безопасным учётным записям, использующим хэши паролей до 4.1. Этот параметр отключён по умолчанию до MySQL 5.6.7, а затем включён.

Проблемы совместимости, связанные с методами хэширования

Расширение столбца Password в MySQL 4.1 с 16 байт до 41 байта влияет на операции установки или обновления следующим образом:

  • При новой установке MySQL столбец Password автоматически устанавливается в 41 байт.

  • Обновление с MySQL 4.1 или более поздней версии до текущих версий MySQL не должно вызывать проблем со столбцом Password, поскольку обе версии используют одинаковую длину столбца и метод хэширования паролей.

  • При обновлении с версии до 4.1 до 4.1 или более поздней версии необходимо обновить системные таблицы после обновления. (См. раздел 4.4.7 «mysql_upgrade — Проверка и обновление таблиц MySQL».)

Метод хэширования 4.1 понимается только серверами и клиентами MySQL 4.1 (и более поздними версиями), что может привести к некоторым проблемам совместимости. Клиент 4.1 или более поздней версии может подключаться к серверу до 4.1, потому что клиент понимает оба метода хэширования паролей до 4.1 и 4.1. Однако клиент до 4.1, пытающийся подключиться к серверу 4.1 или более поздней версии, может столкнуться с трудностями. Например, клиент 4.0 mysql может завершиться с сообщением об ошибке:

$> mysql -h localhost -u root
Client does not support authentication protocol requested
by server; consider upgrading MySQL client

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

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

Способ, которым сервер использует хэши паролей во время аутентификации, зависит от ширины столбца Password:

  • Если столбец короткий, используется только аутентификация с короткими хэшами.

  • Если столбец длинный, он может содержать хэши как короткие, так и длинные, и сервер может использовать любой формат:

    • Клиенты до 4.1 могут подключаться, но поскольку они знают только о методе хэширования до 4.1, они могут пройти аутентификацию только с использованием учётных записей, которые имеют короткие хэши.

    • Клиенты 4.1 и более поздних версий могут пройти аутентификацию с использованием учётных записей, которые имеют короткие или длинные хэши.

Даже для учётных записей с коротким хешем процесса аутентификации фактически немного безопаснее для клиентов 4.1 и более поздних версий, чем для более старых клиентов. С точки зрения безопасности градиент от наименее к наиболее защищенному выглядит так:

  • Клиент до версии 4.1, аутентифицирующийся с коротким хешем пароля

  • Клиент версии 4.1 или более поздней, аутентифицирующийся с коротким хешем пароля

  • Клиент версии 4.1 или более поздней, аутентифицирующийся с длинным хешем пароля

Способ, которым сервер генерирует хеши паролей для подключенных клиентов, зависит от ширины колонки Password и от системной переменной old_passwords. Сервер версии 4.1 или более поздней генерирует длинные хеши только при выполнении определенных условий: колонка Password должна быть достаточно широкой для хранения длинных значений, и системная переменная old_passwords не должна быть установлена в 1.

Эти условия применяются следующим образом:

  • Колонка Password должна быть достаточно широкой для хранения длинных хешей (41 байт). Если колонка не была обновлена и всё ещё имеет ширину до версии 4.1 (16 байт), сервер понимает, что длинные хеши не помещаются в неё, и генерирует только короткие хеши, когда клиент выполняет операции изменения пароля с помощью функции PASSWORD() или оператора генерации паролей. Такое поведение происходит, если вы перешли с версии MySQL, более старой, чем 4.1, на 4.1 или более позднюю версию, но ещё не запустили программу mysql_upgrade для изменения ширины колонки Password.

  • Если колонка Password достаточно широкая, она может хранить короткие или длинные хеши паролей. В этом случае функция PASSWORD() и операторы генерации паролей генерируют длинные хеши, если только сервер не был запущен с установленной системной переменной old_passwords в значение 1 для принудительного создания коротких хешей паролей.

Цель системной переменной old_passwords заключается в обеспечении обратной совместимости с клиентами до версии 4.1 в ситуациях, когда сервер в противном случае сгенерировал бы длинные хеши паролей. Этот параметр не влияет на аутентификацию (клиенты 4.1 и более поздних версий по-прежнему могут использовать учётные записи с длинными хешами паролей), но он предотвращает создание длинного хеша пароля в таблице user в результате операции изменения пароля. Если бы это было разрешено, учётная запись больше не могла бы использоваться клиентами до версии 4.1. При отключённой системной переменной old_passwords возможен следующий нежелательный сценарий:

  • Старый клиент до версии 4.1 подключается к учётной записи, которая имеет короткий хеш пароля.

  • Клиент изменяет свой собственный пароль. При отключённой old_passwords это приводит к тому, что учётная запись получает длинный хеш пароля.

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

Этот сценарий показывает, что если вам необходимо поддерживать более старые клиенты до версии 4.1, проблематично запустить сервер 4.1 или более поздней версии без установленного значения old_passwords в 1. Запустив сервер с old_passwords=1, операции изменения пароля не генерируют длинные хеши паролей и, таким образом, не делают учётные записи недоступными для старых клиентов. (Эти клиенты не могут случайно заблокировать себя, изменив свой пароль и получив длинный хеш пароля.)

Недостатком переменной old_passwords=1 является то, что все созданные или изменённые пароли используют короткие хеши, даже для клиентов 4.1 или более поздних версий. Таким образом, вы теряете дополнительную безопасность, предоставляемую длинными хешами паролей. Чтобы создать учётную запись с длинным хешем (например, для использования клиентами 4.1) или изменить существующую учётную запись для использования длинного хеша пароля, администратор может установить значение сессии old_passwords в 0, оставив глобальное значение равным 1:

mysql> SET @@SESSION.old_passwords = 0;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @@SESSION.old_passwords, @@GLOBAL.old_passwords;
+-------------------------+------------------------+
| @@SESSION.old_passwords | @@GLOBAL.old_passwords |
+-------------------------+------------------------+
|                       0 |                      1 |
+-------------------------+------------------------+
1 row in set (0.00 sec)

mysql> CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'newpass';
Query OK, 0 rows affected (0.03 sec)

mysql> SET PASSWORD FOR 'existinguser'@'localhost' = PASSWORD('existingpass');
Query OK, 0 rows affected (0.00 sec)

Возможны следующие сценарии в MySQL 4.1 или более поздних версиях. Факторами являются то, короткая или длинная колонка Password и, если длинная, запущен ли сервер с включённой или выключенной переменной old_passwords.

Сценарий 1: Короткая колонка Password в таблице пользователей:

  • В колонку Password могут храниться только короткие хеши.

  • Сервер использует только короткие хеши во время аутентификации клиента.

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

  • Значение old_passwords не имеет значения, поскольку при короткой колонке Password сервер в любом случае генерирует только короткие хеши паролей.

Этот сценарий возникает, когда установочная версия MySQL до 4.1 была обновлена до 4.1 или более поздней, но программа mysql_upgrade не была запущена для обновления системных таблиц в базе данных mysql. (Это не рекомендуемая конфигурация, поскольку она не позволяет использовать более безопасное хеширование паролей версии 4.1).

Сценарий 2: Длинная колонка Password; сервер запущен с включённой old_passwords=1:

  • В колонку Password могут храниться короткие или длинные хеши.

  • Клиенты 4.1 и более поздних версий могут аутентифицироваться для учётных записей с короткими или длинными хешами.

  • Клиенты до версии 4.1 могут аутентифицироваться только для учётных записей с короткими хешами.

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

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

Чтобы создать новую учётную запись с длинным хешем пароля или изменить пароль любой существующей учётной записи на использование длинного хеша, сначала установите значение сессии old_passwords в 0, оставив глобальное значение в 1, как описано ранее.

В этом сценарии сервер имеет обновлённую колонку Password, но работает с параметрами хеширования паролей по умолчанию, настроенными на генерацию значений хешей до версии 4.1. Это не рекомендуемая конфигурация, но может быть полезна в переходный период, когда клиенты и пароли до версии 4.1 обновляются до 4.1 или более поздних версий. После этого предпочтительно запустить сервер с включёнными параметрами old_passwords=0 и secure_auth=1.

Сценарий 3: Длинная колонка Password; сервер запущен с включённой old_passwords=0:

  • В колонку Password могут храниться короткие или длинные хеши.

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

  • Клиенты до версии 4.1 могут аутентифицироваться только с помощью учётных записей с короткими хешами.

  • Для подключенных клиентов операции по генерации хешей паролей, связанные с функцией PASSWORD() или операторами генерации паролей, используют исключительно длинные хеши. Изменение пароля учётной записи приводит к тому, что эта учётная запись получает длинный хеш пароля.

Как уже упоминалось, опасность в этом сценарии заключается в том, что учётные записи, которые имеют короткий хеш пароля, могут стать недоступными для клиентов до версии 4.1. Изменение пароля такой учётной записи с помощью функции PASSWORD() или оператора генерации паролей приводит к тому, что учётная запись получает длинный хеш пароля. С этого момента ни один клиент до версии 4.1 не сможет подключиться к серверу с помощью этой учётной записи. Клиент должен обновиться до версии 4.1 или более поздней.

Если это проблема, вы можете изменить пароль особым способом. Например, обычно вы используете SET PASSWORD следующим образом, чтобы изменить пароль учётной записи:

SET PASSWORD FOR 'some_user'@'some_host' = PASSWORD('password');

Чтобы изменить пароль, но создать короткий хеш, используйте функцию OLD_PASSWORD() вместо этого:

SET PASSWORD FOR 'some_user'@'some_host' = OLD_PASSWORD('password');

OLD_PASSWORD() полезно в ситуациях, когда вы явно хотите сгенерировать короткий хеш.

Недостатки каждого из предыдущих сценариев можно обобщить следующим образом:

В сценарии 1 вы не можете использовать более длинные хеши, которые обеспечивают более безопасную аутентификацию.

В сценарии 2, old_passwords=1 предотвращает блокировку учетных записей с короткими хешами, но операции изменения паролей приводят к возврату учетных записей с длинными хешами к коротким, если вы не позаботитесь о предварительном изменении значения сеанса old_passwords на 0.

В сценарии 3, учетные записи с короткими хешами становятся недоступными для клиентов версии до 4.1, если вы изменяете их пароли без явного использования OLD_PASSWORD().

Лучший способ избежать проблем совместимости, связанных с короткими хешами паролей, — не использовать их:

  • Обновите все клиентские программы до MySQL 4.1 или более поздней версии.

  • Запустите сервер с old_passwords=0.

  • Сбросьте пароль для любой учетной записи с коротким хешем пароля, чтобы использовать длинный хеш пароля.

  • Для дополнительной безопасности запустите сервер с secure_auth=1.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/password-hashing.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API