mysqljs / mysql

A pure node.js JavaScript Client implementing the MySQL protocol.
MIT License
18.29k stars 2.52k forks source link

Lack of support for sha256_password authentication plugin #1758

Open elemount opened 7 years ago

elemount commented 7 years ago

I'm using MySQL with sha256_password authentication plugin(https://dev.mysql.com/doc/refman/5.7/en/sha256-pluggable-authentication.html). This mainly because SHA1 which MySQL defaults is not secure. Please refer http://mysqlserverteam.com/protecting-mysql-passwords-with-the-sha256_password-plugin/ and https://blog.qualys.com/ssllabs/2014/09/09/sha1-deprecation-what-you-need-to-know I fount mysqljs do not support this feature yet? Do you have any plan to support it? If not, could I contribute some code for that?

sidorares commented 7 years ago

probably needs #1730 to land first. Auth switch is very similar to plugin authentication

sidorares commented 7 years ago

@elemount do you know any more details about what's actually sent with sha256_password handshake? Trying to make simple POC using mysql2 and authSwitch request handler

Documentation is not great, from what I see is that password is encrypted using rsa public key if there is no ssl ( and public key is configured ), but not sure what other transformations applied. I can see same 20 bytes salt as wit mysql_native_password. Might just try same xor(sha1(salt, sha1(sha1(password)), sha1(password))

elemount commented 7 years ago

@sidorares This commit on PyMySQL can explain how sha256_password https://github.com/PyMySQL/PyMySQL/pull/583/commits/1f6280371d449cbd5198937592232f9bb747cbbc . Only about 60 line for whole auth.

sidorares commented 7 years ago

thanks for the link @elemount , very helpful!

sidorares commented 7 years ago

summary from PyMySQL:

server: AuthSwitch('sha256_password', 20 bytes salt) ( actually 21, last one is always 0, only 20 used ) client: if no SSL and public key provided: respond with RSA(xor(password + \0, salt))

if SSL respond with password + '\0' ( this failed for me but I might did something wrong )

if no SSL and no public key - fail

elemount commented 7 years ago

@sidorares

  1. mysqld with default_auth_plugin=sha256_password, and use SSL, server say sha256, client and server get SSL, and then client response sha256 password directly.
  2. mysqld with default_auth_plugin=sha256_password, and do not use SSL, server say sha256, client response sha256, server (1) auth switch (2) tell the RSA public key directly, then client response the encrypted password.
  3. mysqld with default_auth_plugin=mysql_native_password(By default), and use SSL, server say native, client and server get SSL, and then client response native, and server say AuthSwith to sha256_password, the client reponse the password directly.
  4. mysqld with default_auth_plugin=mysql_native_password(By default), and do not use SSL, server say native, client say native, server say AuthSwith, and the client get RSA(already have or request '1' then server response public key) and response the encrypted password.

And client driver can provide the public key, it no public key, client driver can send packet with 0x01 which means AuthMoreData to retrieve public key.

sidorares commented 7 years ago

2 seems strange. If traffic is unencrypted MITM could replace key then decode passord and re-encode using server key

I'm testing using instructions from https://dev.mysql.com/doc/refman/5.7/en/sha256-pluggable-authentication.html - default plugin is still native auth, just one single user with sha256_password created, client connects with this user name/pass and then tries to handle auth switch

sidorares commented 7 years ago

@elemount could you assist me in setting up mysql server? I'm using docker, and it keeps complaining about unknown variable 'sha256_password_private_key_path

I suspect version on docker hub is built using YaSSL and does not have rsa support. Do you know any other image that allows easy keys configuration ( or have them pre configured ) ?

docker run -it -v C:\Projects\node-mysql2:/keys -v C:\Projects\node-mysql2:/etc/mysql/conf.d -e MYSQL_ALLOW_EMPTY_PASSWORD=1 -e MYSQL_DATABASE=test -p 33306:3306 mysql:5.7.18

elemount commented 7 years ago

@sidorares mysql which support sha256_password with RSA must built with openssl, by cmake -DWITH_SSL=system. Default is built with YaSSL. Let me find a way to deliver a MySQL docker image with openssl.