關於MySQL密碼你應該知道的那些事

運維之美CENALULU'S2018-03-21 13:04:10

本文將介紹MySQL相關的一些知識,以及5.6中對於安全性的一些改進。


MySQL用戶密碼是如何生成和保存的

如果你已經接觸MySQL一段時間了,那麼想必你一定知道MySQL把所有用戶的用戶名和密碼的存放在mysql.user表中。大致的形式如下:

mysql [localhost] {msandbox} (mysql) > select user,password from mysql.user;
+----------------+-------------------------------------------+
| user           | password                                  |
+----------------+-------------------------------------------+
| root           | *6C387FC3893DBA1E3BA155E74754DA6682D04747 |
| plain_password | *861D75A7F79DE84B116074893BBBA7C4F19C14FA |
| msandbox       | *6C387FC3893DBA1E3BA155E74754DA6682D04747 |
| msandbox       | *6C387FC3893DBA1E3BA155E74754DA6682D04747 |
| msandbox_rw    | *6C387FC3893DBA1E3BA155E74754DA6682D04747 |
| msandbox_rw    | *6C387FC3893DBA1E3BA155E74754DA6682D04747 |
| msandbox_ro    | *6C387FC3893DBA1E3BA155E74754DA6682D04747 |
| msandbox_ro    | *6C387FC3893DBA1E3BA155E74754DA6682D04747 |
| rsandbox       | *B07EB15A2E7BD9620DAE47B194D5B9DBA14377AD |
+----------------+-------------------------------------------+
9 rows in set (0.01 sec)*


可見MySQL在其內部是不存放用戶的的(這個也是一般程序對於敏感信息的最基礎保護)。一般來說密文是通過不可逆加密算法得到的。這樣即使敏感信息洩漏,除了暴力破解是無法快速從密文直接得到明文的。

MySQL用的是哪種不可逆算法來加密用戶密碼的

MySQL實際上是使用了兩次SHA1夾雜一次unhex的方式對用戶密碼進行了加密。具體的算法可以用公式表示:password_str = concat(‘*’, sha1(unhex(sha1(password)))) 我們可以用下面的方法做個簡單的驗證。

mysql [localhost] {msandbox} (mysql) > select password('mypassword'),concat('*',sha1(unhex(sha1('mypassword'))));
+-------------------------------------------+---------------------------------------------+
| password('mypassword')                    | concat('*',sha1(unhex(sha1('mypassword')))) |
+-------------------------------------------+---------------------------------------------+
| *FABE5482D5AADF36D028AC443D117BE1180B9725 | *fabe5482d5aadf36d028ac443d117be1180b9725   |
+-------------------------------------------+---------------------------------------------+
1 row in set (0.01 sec)


MySQL用戶密碼的不安全性

其實MySQL在5.6版本以前,對於對於安全性的重視度非常低,對於用戶密碼也不例外。例如,MySQL對於binary log中和用戶密碼相關的操作是不加密的。如果你向MySQL發送了例如create user,grant user … identified by這樣的攜帶初始明文密碼的指令,那麼會在binary log中原原本本的被還原出來。我們通過下面的例子來驗證

創建一個用戶

mysql [localhost] {msandbox} (mysql) > create user plain_password identified by 'plain_pass';
Query OK, 0 rows affected (0.00 sec)

用mysqlbinlog查看二進制日誌

shell> mysqlbinlog binlog.000001# at 106#150227 23:37:59 server id 1  end_log_pos 223   Query   thread_id=1 exec_time=0 error_code=0use mysql/*!*/;
SET TIMESTAMP=1425051479/*!*/;
SET @@session.pseudo_thread_id=1/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=0/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C latin1 *//*!*/;
SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
create user plain_password identified by 'plain_pass'/*!*/;
DELIMITER ;# End of log fileROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;

MySQL5.6中對於用戶密碼的安全性加強

好在MySQL5.6開始對安全性有了一定的重視,為了杜絕明文密碼出現在binlog中的情況,MySQL引入了一系列會以密文方式記錄二進制日誌的命令:

  • REATE USER … IDENTIFIED BY …

  • GRANT … IDENTIFIED BY …

  • SET PASSWORD …

  • SLAVE START … PASSWORD = … (as of 5.6.4)

  • CREATE SERVER … OPTIONS(… PASSWORD …) (as of 5.6.9)

  • ALTER SERVER … OPTIONS(… PASSWORD …) (as of 5.6.9)


細心你的也許會發現,change master to master_password=’’命令不在這個範疇中。這也就意味著MySQL5.6中仍然使用這樣的語法來啟動replication時有安全風險的。這也就是為什麼5.6中使用帶有明文密碼的change master to時會有warning提示,具體如下:

slave1 [localhost] {msandbox} ((none)) > change master to master_host='127.0.0.1',master_port =21288,master_user='rsandbox',master_password='rsandbox',master_auto_position=1;
Query OK, 0 rows affected, 2 warnings (0.04 sec)

slave1 [localhost] {msandbox} ((none)) > show warnings;
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                                                                                                                                                                                              |
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Note  | 1759 | Sending passwords in plain text without SSL/TLS is extremely insecure.                                                                                                                                                                                                               |
| Note  | 1760 | Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information. |
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

reference: http://www.pythian.com/blog/hashing-algorithm-in-mysql-password-2/


來源:CENALULU'S TECH BLOG

原文:http://t.cn/R2Z9HMO

題圖:來自谷歌圖片搜索

版權:本文版權歸原作者所有



更多精彩熱文:


  • 理解Nginx實現原理

  • Apache/Nginx通過UserAgent屏蔽蜘蛛和採集

  • 如何獲取NGINX多層轉發或使用CDN之後的用戶真實IP

  • 使用Mosh來優化SSH連接 

  • 如何成為一名優秀的全棧工程師



閱讀原文

TAGS: