Mysql

當密碼儲存在選項文件中時 MySQL 拒絕登錄嘗試

  • July 30, 2016

第一的:

  • 我們正在執行 MySQL 5.7.13。
  • 作業系統是 Red Hat Enterprise Linux 7.2。
  • 該問題最初是使用 Python/Connector 2.1.3 發現的
  • 系統未加入域(尚未。)
  • 從 MySQL 自己的 yum 儲存庫安裝的所有 MySQL 軟體包!

場景:我正在嘗試建構一個簡單的監控解決方案,以密切關注我控制的目前一百多台機器的某些方面(並且在不久的將來可能會增加數量);我需要能夠生成安全報告,例如,給他們包版本以證明最近披露的漏洞已在 x 台機器上得到修補。

我可以使用 Ansible 等人實時提取這些資訊,但是 a) 不能保證所有機器在任何給定時間都會連接,並且 b) 管理工具可以給我目前狀態,但不一定是我可能需要的歷史數據報告。所以從我的角度來看,解決方案是一個可以容納每個系統記錄的數據庫;當系統更新時,我們將一條新記錄放入數據庫中以指示更改,然後我可以稍後將其提取出來。

為此,我們使用 MySQL 數據庫。目前,我們有一個簡單的準系統 MySQL 安裝,其中創建了一個小表集並定義了一個非 root 使用者。MySQL中定義的使用者列表是:

select user, host, authentication_string from mysql.user;
+-------------+-----------+-------------------------------------------+
| user        | host      | authentication_string                     |
+-------------+-----------+-------------------------------------------+
| root        | localhost | *D971D136A477A4C205AEF706...              |
| mysql.sys   | localhost | *THISISNOTAVALIDPASSWORDT...              |
| pkg_manager | localhost | *E91158E2E26F343D6639E4BD...              |
+-------------+-----------+-------------------------------------------+

所以不存在空字元串使用者名。

有問題的帳戶是 pkg_manager 帳戶。授予它的權限是:

mysql> show grants for 'pkg_manager'@'localhost';
+-------------------------------------------------------------------------------------+
| Grants for pkg_manager@localhost                                                    |
+-------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'pkg_manager'@'localhost'                                     |
| GRANT SELECT, INSERT ON `panopticon`.`package` TO 'pkg_manager'@'localhost'         |
| GRANT SELECT, INSERT ON `panopticon`.`package_history` TO 'pkg_manager'@'localhost' |
+-------------------------------------------------------------------------------------+

pkg_manager 帳戶連接沒有問題,使用如下命令行:

[~]$ mysql -u pkg_manager -p --database=panopticon
Enter password: 
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.7.13 MySQL Community Server (GPL)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

但是,我需要允許自動化工具登錄數據庫(它將提取目前不是最新的系統列表,檢查其中哪些目前線上,然後將更新推送給它們並記錄每個成功更新。)該工具將使用 Python 編寫,並且我已拉下 Python 2.1.3 連接器。

我們為該工具建構了一個 options.cnf 文件,並將其儲存在一個受限制的目錄中(最初是 root:root 0700,目前是一個 :。通過連接器在 python 中打開連接的初始測試:

connection = mysql.connector.connect(option_files='/path/to/options.cnf')

導致錯誤 1045,SQLState 28000 消息。(實際上,首先還有一些其他的事情,主要涉及指定套接字路徑。然而,這些都被清除了,我們知道它們已經不礙事了,因為現在 MySQL 日誌正在報告失敗的連接嘗試。)

我們知道這部分有效,因為 1045 錯誤的完整詳細資訊是“使用者 ‘pkg_manager’@’localhost’ 的訪問被拒絕(使用密碼:YES)”。所以它正在讀取選項文件,它正在辨識 pkg_manager 帳戶,並且它正在查看文件中的密碼條目(如果不存在密碼條目,則消息的結尾變為“(使用密碼:否)”。

然後,我們嘗試通過使用相同的選項文件來簡化問題,並在其中創建一個客戶端部分,指定出現在 connector_python 部分中的所有相同欄位。這也失敗了:

mysql --defaults-file="/path/to/options.cnf"

但是,我們知道在命令行上手動指定登錄資訊時該帳戶有效,如上所示。

經過數小時搜尋登錄失敗的使用者體驗後,我們決定嘗試一種混合方法 - 使用 –defaults 文件進行命令行登錄,同時還指定 -p 以強制我們在命令行中輸入密碼:

[~]$ mysql --defaults-file="/etc/pkg_manager/db_info/options.cnf" -p
Enter password: 
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
...
mysql>

因此,我們知道 options conf 文件中提供的其餘資訊是正確的。簡單地執行 mysql –print-defaults (以確定路徑搜尋列表中是否有任何其他選項文件可能會干擾)會導致列出的啟動選項為零,因此沒有其他選項可以阻止。

在這一點上,我幾乎被困住了。MySQL 官方文件明確指出,除了加密的本地登錄文件之外,您還可以將未加密的密碼儲存在選項文件中:http: //dev.mysql.com/doc/refman/5.7/en/password-security-user.html

然而,很明顯,它不起作用。我查看了可以設置的配置文件變數列表,我沒有看到任何似乎會阻止來自選項文件的密碼驗證的內容。我已將錯誤日誌記錄設置為 3,但沒有提供有關連接問題的詳細資訊,除了一條表明來自 ‘pkg_manager’@’localhost’ 的連接嘗試被拒絕的單行註釋。

在我忘記之前,這是選項文件(無密碼):

1 # Options file for pkg_manager, easy way to "securely" store database login info.
2 [connector_python]
3 user="pkg_manager"
4 password="*********"
5 database="panopticon"
6 host="localhost"
7 unix_socket="/var/lib/mysql/mysql.sock"
8 
9 [client]
10 user="pkg_manager"
11 password="*********"
12 database="panopticon"
13 host="localhost"
14 socket="/var/lib/mysql/mysql.sock"

這是 /etc/my.cnf 文件:

1 # For advice on how to change settings please see
2 # http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
3 
4 [mysqld]
5 #
6 # Remove leading # and set to the amount of RAM for the most important data
7 # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
8 # innodb_buffer_pool_size = 128M
9 #
10 # Remove leading # to turn on a very important data integrity option: logging
11 # changes to the binary log between backups.
12 # log_bin
13 #
14 # Remove leading # to set options mainly useful for reporting servers.
15 # The server defaults are faster for transactions and fast SELECTs.
16 # Adjust sizes as needed, experiment to find the optimal values.
17 # join_buffer_size = 128M
18 # sort_buffer_size = 2M
19 # read_rnd_buffer_size = 2M
20 datadir=/data/panopticon
21 socket=/var/lib/mysql/mysql.sock
22 
23 skip-networking
24 
25 # Disabling symbolic-links is recommended to prevent assorted security risks
26 symbolic-links=0
27 
28 log-error=/var/log/mysqld.log
29 log_error_verbosity=3
30 general-log=1
31 general_log_file=/var/log/mysql_general.log
32 pid-file=/var/run/mysqld/mysqld.pid

我終於有機會再花幾個小時來研究這個問題,我找到了解決方案。正如我所想的那樣,它簡單得令人沮喪,但它也違背了多個使用者論壇甚至 MySQL 參考文件上發布的建議。

如果我的密碼儲存在引號中的選項文件中,它將無法連接。當我從密碼中刪除引號時,它會連接。在我意識到這一點之前,我最終瀏覽了 Python 連接器程式碼,主要是因為我之前嘗試過刪除密碼上的引號,但是對於一個稍微不同的問題,然後在我的腦海中將這兩個問題混為一談。

我注意到,在瀏覽 Python 連接器程式碼時,我可以直接實例化一個選項文件解析器,所以我試了一下(將我的選項文件的路徑作為參數傳遞。)當我這樣做時,我看到了所有選項,包括密碼,被導入到解析器狀態,並帶有文件中的任何引用。但是,在那之後的任何階段都沒有採取措施從密碼中刪除引號(至少我看到了),所以當連接器使用解析器打開選項文件時,引號被包含並傳遞給伺服器作為密碼的一部分進行身份驗證。

我很可能會將其作為向 MySQL 開發人員報告的錯誤報告,因為所有其他選項都可以正常使用引號。

引用自:https://serverfault.com/questions/788718