Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mysqlnd fails to authenticate with sha256_password accounts using passwords longer than 19 characters. #11438

Closed
weigon opened this issue Jun 12, 2023 · 3 comments

Comments

@weigon
Copy link

weigon commented Jun 12, 2023

Description

The following code:

<?php
// CREATE USER sha256_20 IDENTIFIED WITH sha256_password BY '01234567890123456789';
// CREATE USER sha256_19 IDENTIFIED WITH sha256_password BY '0123456789012345678';
new mysqli("127.0.0.1", "sha256_19", "0123456789012345678");
new mysqli("127.0.0.1", "sha256_20", "01234567890123456789");

Resulted in this output:

PHP Fatal error:  Uncaught mysqli_sql_exception: Access denied for user 'sha256_20'@'localhost' (using password: YES) in Command line code:1
Stack trace:
#0 Command line code(1): mysqli->__construct()
#1 {main}
  thrown in Command line code on line 1

But I expected this output instead:

With the mysql client, authentication works as expected.

$ mysqladmin --user=sha256_19 --password=0123456789012345678   ping
mysqld is alive
$ mysqladmin --user=sha256_20 --password=01234567890123456789 ping
mysqld is alive

PHP Version

PHP 8.1.2

Operating System

Ubuntu 22.04

@nielsdos
Copy link
Member

nielsdos commented Jun 12, 2023

I think there's an off-by-one in mysqlnd_xor_string. If I subtract 1 from the xor_str_len in the modulo operand, it seems to work... I'll dig a bit deeper.
EDIT: I think it works with -1 because it ends up with a length of 20, which interestingly equals SCRAMBLE_LENGTH.

nielsdos added a commit to nielsdos/php-src that referenced this issue Jun 12, 2023
…ccounts using passwords longer than 19 characters

https://dev.mysql.com/doc/dev/mysql-server/latest/page_caching_sha2_authentication_exchanges.html
tells us that the nonce used in this authentication method is 20 bytes
long. However, we might receive additional scramble data in
php_mysqlnd_greet_read not used in this method.
On my test setup, I received 21 bytes (20 bytes + '\0'). This resulted
in the xor computation to incorrectly include the NUL byte. Every
password of at least 20 characters therefore failed to authenticate
using this method.

Looking at mysql-server source code also seems to reveal that it always
uses a fixed number of scramble bytes [1].

[1] https://github.com/mysql/mysql-server/blob/ea7087d885006918ad54458e7aad215b1650312c/sql/auth/sha2_password.cc#L1078-L1079
@MohamedAbuZamil
Copy link

The behavior you are experiencing is related to how PHP's mysqli extension handles the connection authentication method when using the sha256_password plugin.

In MySQL 8.0.4 and later, a new default authentication plugin was introduced called caching_sha2_password, which is more secure than the older mysql_native_password plugin. However, PHP's mysqli extension doesn't fully support this new default plugin, and that's why you are encountering the "Access denied" error for the user 'sha256_20'.

To resolve this issue, you have a couple of options:

  1. Use a Supported Authentication Plugin: Change the authentication method for the user 'sha256_20' to use the mysql_native_password plugin instead of sha256_password. This way, PHP's mysqli extension should be able to authenticate successfully.

    For example:

    ALTER USER 'sha256_20'@'localhost' IDENTIFIED WITH mysql_native_password BY '01234567890123456789';
  2. Use MySQL Native Driver (mysqlnd): The mysqli extension can work seamlessly with the MySQL Native Driver (mysqlnd), which is a PHP native driver for MySQL. It provides better compatibility with the new authentication plugins, including caching_sha2_password.

    To use mysqlnd, you need to make sure it is enabled in your PHP configuration. Look for the following line in your php.ini file:

    ;extension=mysqlnd
    

    Uncomment it by removing the semicolon and restart your web server.

    With mysqlnd enabled, the mysqli extension should be able to handle the sha256_password plugin without any issues.

Note that using mysqlnd is generally recommended for better compatibility with the latest MySQL features and improvements. However, if you have a specific need to stick with sha256_password, you can use the first option to switch the authentication plugin for the 'sha256_20' user.

Remember to restart your web server (e.g., Apache or Nginx) after making any changes to the PHP configuration.

@nielsdos
Copy link
Member

nielsdos commented Aug 3, 2023

@MohamedAbuZamil your answer doesn't make sense. Please refrain from posting nonsense AI-generated content.

nielsdos added a commit that referenced this issue Aug 3, 2023
* PHP-8.1:
  Fix GH-10964: Improve `man` page about the built-in server
  Fix GH-11438: mysqlnd fails to authenticate with sha256_password accounts using passwords longer than 19 characters
nielsdos added a commit that referenced this issue Aug 3, 2023
* PHP-8.2:
  Fix GH-10964: Improve `man` page about the built-in server
  Fix GH-11438: mysqlnd fails to authenticate with sha256_password accounts using passwords longer than 19 characters
jorgsowa pushed a commit to jorgsowa/php-src that referenced this issue Aug 16, 2023
…ccounts using passwords longer than 19 characters

https://dev.mysql.com/doc/dev/mysql-server/latest/page_caching_sha2_authentication_exchanges.html
tells us that the nonce used in this authentication method is 20 bytes
long. However, we might receive additional scramble data in
php_mysqlnd_greet_read not used in this method.
On my test setup, I received 21 bytes (20 bytes + '\0'). This resulted
in the xor computation to incorrectly include the NUL byte. Every
password of at least 20 characters therefore failed to authenticate
using this method.

Looking at mysql-server source code also seems to reveal that it always
uses a fixed number of scramble bytes [1].

[1] https://github.com/mysql/mysql-server/blob/ea7087d885006918ad54458e7aad215b1650312c/sql/auth/sha2_password.cc#L1078-L1079

Closes phpGH-11445.

Co-authored-by: Kamil Tekiela <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants