Bug #78680 [Opn->Csd]: mysqlnd's mysql_clear_password does not transmit null-terminated password

From: Date: Mon, 15 Feb 2021 10:33:30 +0000
Subject: Bug #78680 [Opn->Csd]: mysqlnd's mysql_clear_password does not transmit null-terminated password
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-232163@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=78680&edit=1 ID: 78680 Updated by: nikic@php.net Reported by: geoff dot montee at gmail dot com Summary: mysqlnd's mysql_clear_password does not transmit null-terminated password -Status: Open +Status: Closed Type: Bug Package: MySQLi related Operating System: Alpine Linux v3.10 PHP Version: 7.3.10 Block user comment: N Private report: N New Comment: Automatic comment on behalf of daniel@mariadb.org Revision: http://git.php.net/?p=php-src.git;a=commit;h=3646604203d80bc0f6a124aa2ac5c448229327ea Log: Fix #78680: mysqlnd pam plugin missing terminating null Previous Comments: ------------------------------------------------------------------------ [2021-02-05 21:38:51] geoff dot montee at gmail dot com The following pull request has been associated: Patch Name: Fix #78680: mysqlnd pam plugin missing terminating null On GitHub: https://github.com/php/php-src/pull/6667 Patch: https://github.com/php/php-src/pull/6667.patch ------------------------------------------------------------------------ [2021-01-13 16:36:33] cmb@php.net Well, that looks indeed wrong in mysqldn. Would you mind to provide a pull request[1]? [1] <https://github.com/php/php-src/pulls> ------------------------------------------------------------------------ [2019-10-17 19:34:45] geoff dot montee at gmail dot com This problem was discovered due to the following two MariaDB bug reports: https://jira.mariadb.org/browse/MDEV-19882 https://jira.mariadb.org/browse/MDEV-20571 ------------------------------------------------------------------------ [2019-10-17 18:47:07] geoff dot montee at gmail dot com Description: ------------ The mysql_clear_password client authentication plugin is supposed to transmit a null-terminated password to the server. This is described in the following code comment: " @startuml Server->Client: 20 bytes of scramble to be ignored Client->Server: The clear text password. null terminated. @enduml" https://github.com/mysql/mysql-server/blob/mysql-8.0.18/sql-common/client.cc#L8469 PHP's implementation of mysql_clear_password in the mysqlnd driver does not seem to transmit the terminating NULL character with the password. See here: https://github.com/php/php-src/blob/php-7.3.10/ext/mysqlnd/mysqlnd_auth.c#L610 https://github.com/php/php-src/blob/php-7.3.10/ext/mysqlnd/mysqlnd_auth.c#L115 This can easily be reproduced. --- Let's say that I have a server running MariaDB 10.4.8. We can configure PAM authentication by performing the following steps: 1.) Create a Unix user account and set a password for the user: sudo useradd alice sudo passwd alice The examples below assume that the password is "uGBXHxID3dJRALw2". 2.) Create the PAM service configuration: sudo tee /etc/pam.d/mariadb <<EOF auth required pam_unix.so audit account required pam_unix.so audit EOF 3.) Install the pam plugin: sudo mysql --execute="INSTALL SONAME 'auth_pam'" 4.) Create the relevant user: sudo mysql --execute="CREATE USER 'alice'@'localhost' IDENTIFIED VIA pam USING 'mariadb'" 5.) Enable the pam_use_cleartext_plugin system variable: $ sudo mysql -u root --execute="SHOW GLOBAL VARIABLES LIKE 'pam%'" +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | pam_use_cleartext_plugin | ON | | pam_winbind_workaround | OFF | +--------------------------+-------+ At this point, PAM is configured. --- Let's say that I set up PHP 7.3.10 on the same server as the database. The connectivity can easily be tested by creating the following test script: tee pamtest.php << EOF <?php \$link = mysqli_connect("127.0.0.1", "alice", "uGBXHxID3dJRALw2", "test"); if (!\$link) { echo "Error: Unable to connect to MySQL." . PHP_EOL; echo "Debugging errno: " . mysqli_connect_errno() . PHP_EOL; echo "Debugging error: " . mysqli_connect_error() . PHP_EOL; exit; } echo "Success: A proper connection to MySQL was made! The my_db database is great." . PHP_EOL; echo "Host information: " . mysqli_get_host_info(\$link) . PHP_EOL; mysqli_close(\$link); ?> EOF php -f pamtest.php --- So let's run the test script, and do some debugging. 1.) First, let's attach strace to the mysqld process: sudo mkdir strace/ cd strace/ sudo strace -o strace.out -f -ff -p $(pidof mysqld) 2.) And then let's also run the PHP script while attaching strace to that process: strace -o strace.out -f -ff php -f pamtest.php Authentication will fail on MariaDB 10.4.8, since that MariaDB version currently treats the NULL terminating character as mandatory: Warning: mysqli_connect(): (HY000/1045): Access denied for user 'alice'@'localhost' (using password: NO) in /var/www/html/pamtest.php on line 2 Error: Unable to connect to MySQL. Debugging errno: 1045 Debugging error: Access denied for user 'alice'@'localhost' (using password: NO) The strace output of the PHP script shows that the NULL terminating character is not set: ./strace.out.3393-recvfrom(3, "\26\0\0\2\376mysql_clear_password\0", 32768, MSG_DONTWAIT, NULL, NULL) = 26 ./strace.out.3393:sendto(3, "\20\0\0\3uGBXHxID3dJRALw2", 20, MSG_DONTWAIT, NULL, 0) = 20 And the strace output of mysqld shows the same thing: sendto(154, "\26\0\0\2\376mysql_clear_password\0", 26, MSG_DONTWAIT, NULL, 0) = 26 recvfrom(154, "\20\0\0\3", 4, MSG_DONTWAIT, NULL, NULL) = 4 recvfrom(154, "uGBXHxID3dJRALw2", 16, MSG_DONTWAIT, NULL, NULL) = 16 In contrast, here's the strace output of mysqld with a "working" client: sendto(154, "\26\0\0\2\376mysql_clear_password\0", 26, MSG_DONTWAIT, NULL, 0) = 26 recvfrom(154, "\21\0\0\3", 4, MSG_DONTWAIT, NULL, NULL) = 4 recvfrom(154, "uGBXHxID3dJRALw2\0", 17, MSG_DONTWAIT, NULL, NULL) = 17 ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=78680&edit=1

« previous php.bugs (#232163) next »