MYSQL 安全

renjixinchina發表於2012-08-29

轉載時請務必以超連結形式標明文章和作者資訊及。 
連結: 
     MySQL 是一個真正的多使用者、多執行緒SQL資料庫伺服器,它是一個客戶機/伺服器結構的實現。MySQL是現在流行的關聯式資料庫中其中的一種,相比其它的資料庫管理系統(DBMS)來說,MySQL具有小巧、功能齊全、查詢迅捷等優點。MySQL 主要目標是快速、健壯和易用。目前,在大中型企業中已經得到了較好的運用,但是由於它是多平臺的資料庫,不可避免的預設配置也是適合多種情況的需求,因此需要使用者需要在自定義的環境下對MySQL的使用進行加固。

      假如軟體本身有嚴重安全問題,即使安全配置做的更好,也沒有用。因此,要首先了解MySQL的版本。關於MySQL的版本,在MySQL官方文件中是這麼描述的:
    MySQL 5.2是最新開發的釋出系列,是將執行新功能的系列。不久的將來可以使用Alpha發行,以便感興趣的使用者進行廣泛的測試。
    MySQL 5.1是當前穩定(產品質量)釋出系列。只針對漏洞修復重新發布;沒有增加會影響穩定性的新功能。
    MySQL 5.0是前一穩定(產品質量)釋出系列。只針對嚴重漏洞修復和安全修復重新發布;沒有增加會影響該系列的重要功能。
    MySQL 4.0和3.23是舊的穩定(產品質量)釋出系列。該版本不再使用,新的釋出只用來修復特別嚴重的漏洞(以前的安全問題)。
Mysql開發組織不認為有完全的凍結版,因為任何版本均需要對漏洞進行修復和其它修復。對於"某種程度的凍結",他們是指他們可以在產品釋出中增加一些不會影響當前工作的小東西。當然,前一系列的相關漏洞修復會移植到後面的系列。

根據官方的建議,至目前為止,推薦使用目前的穩定版本MySQL 5.1。如果你正在執行一個老的系統並且想要升級,但是又不想冒險進行非無縫升級,應該升級到最新版本中你正使用的相同的釋出系列(只有版本號的最後部分比你使用的新,例如5.0和5.1為同一系列)。

一、MySQL安裝

MySQL可以在redhat環境下進行RPM安裝和debian下apt安裝,但是最新的包一般都是原始碼的形式,因此這裡選擇原始碼編譯安裝的方式。
首先登陸官方網站,下載最新的released版本。
# tar zxf mysql-5.1.22-rc-linux-i686-glibc23.tar.gz
為mysql的執行建立mysql使用者和mysql使用者組
#groupadd mysql
# useradd -g mysql mysql
# ./configure --prefix=/usr/local/mysql
#make
#make install
# cp support-files/my-medium.cnf /etc/my.cf
# bin/mysql_install_db --user=mysql //用mysql生成初始資料庫,出現類似thank for using mysql 證明初始化資料庫成功。
# chown -R root .  //當前目錄給root
# chown -R mysql var //var給mysql,這個很重要,也是安全起見
# chgrp -R mysql .
# bin/mysqld_safe --user=mysql &
#bin/mysql -u root
此時安全完畢,但是最重要是對MySQL進行安全配置,檢查你的系統,最基本要做到以下配置。

二、MySQL安全配置

資料庫作為資料管理的平臺,它的安全性首先由系統的內部安全和網路安全兩部分來決定。對於系統管理員來說,首先要保證系統本身的安全,在安裝MySQL資料庫時,需要對基礎環境進行較好的配置。

1、修改root使用者口令,刪除空口令
預設安裝的MySQL的root使用者是空密碼的,為了安全起見,必須修改為強密碼,所謂的強密碼,至少8位,由字母、數字和符號組成的不規律密碼。使用MySQL自帶的命令mysaladmin修改root密碼,同時也可以登陸資料庫,修改資料庫mysql下的user表的欄位內容,修改方法如下所示:

# /usr/local/mysql/bin/mysqladmin -u root password "upassword" //使用mysqladmin
#mysql> use mysql; 
#mysql> update user set password=password('upassword') where user='root'; 
#mysql> flush privileges; //強制重新整理記憶體授權表,否則用的還是在記憶體緩衝的口令

2、刪除預設資料庫和資料庫使用者
一般情況下,MySQL資料庫安裝在本地,並且也只需要本地的php指令碼對mysql進行讀取,所以很多使用者不需要,尤其是預設安裝的使用者。MySQL初始化後會自動生成空使用者和test庫,進行安裝的測試,這會對資料庫的安全構成威脅,有必要全部刪除,最後的狀態只保留單個root即可,當然以後根據需要增加使用者和資料庫。

#mysql> show databases;
#mysql> drop database test; //刪除資料庫test
#use mysql;
#delete from db; //刪除存放資料庫的表資訊,因為還沒有資料庫資訊。
#mysql> delete from user where not (user='root') ; // 刪除初始非root的使用者
#mysql> delete from user where user='root' and password=''; //刪除空密碼的root,儘量重複操作
Query OK, 2 rows affected (0.00 sec)
#mysql> flush privileges; //強制重新整理記憶體授權表。

3、改變預設mysql管理員帳號
系統mysql的管理員名稱是root,而一般情況下,資料庫管理員都沒進行修改,這一定程度上對系統使用者窮舉的惡意行為提供了便利,此時修改為複雜的使用者名稱,請不要在設定為admin或者administraror的形式,因為它們也在易猜的使用者字典中。

mysql> update user set user="newroot" where user="root"; //改成不易被猜測的使用者名稱
mysql> flush privileges;

4、關於密碼的管理
密碼是資料庫安全管理的一個很重要因素,不要將純文字密碼儲存到資料庫中。如果你的計算機有安全危險,入侵者可以獲得所有的密碼並使用它們。相反,應使用MD5()、SHA1()或單向雜湊函式。也不要從詞典中選擇密碼,有專門的程式可以破解它們,請選用至少八位,由字母、數字和符號組成的強密碼。在存取密碼時,使用mysql的內建函式password()的sql語句,對密碼進行加密後儲存。例如以下方式在users表中加入新使用者。

#mysql> insert into users values (1,password(1234),'test');

5、使用獨立使用者執行msyql
絕對不要作為使用root使用者執行MySQL伺服器。這樣做非常危險,因為任何具有FILE許可權的使用者能夠用root建立檔案(例如,~root/.bashrc)。mysqld拒絕使用root執行,除非使用--user=root選項明顯指定。應該用普通非特權使用者執行mysqld。正如前面的安裝過程一樣,為資料庫建立獨立的linux中的mysql賬戶,該賬戶用來只用於管理和執行MySQL。

要想用其它Unix使用者啟動mysqld,,增加user選項指定/etc/my.cnf選項檔案或伺服器資料目錄的my.cnf選項檔案中的[mysqld]組的使用者名稱。
#vi /etc/my.cnf
[mysqld]
user=mysql
該命令使伺服器用指定的使用者來啟動,無論你手動啟動或透過mysqld_safe或mysql.server啟動,都能確保使用mysql的身份。也可以在啟動資料庫是,加上user引數。

# /usr/local/mysql/bin/mysqld_safe --user=mysql &
作為其它linux使用者而不用root執行mysqld,你不需要更改user表中的root使用者名稱,因為MySQL賬戶的使用者名稱與linux賬戶的使用者名稱無關。確保mysqld執行時,只使用對資料庫目錄具有讀或寫許可權的linux使用者來執行。

6、禁止遠端連線資料庫
在命令列netstat -ant下看到,預設的3306埠是開啟的,此時開啟了mysqld的網路監聽,允許使用者遠端透過帳號密碼連線數本地據庫,預設情況是允許遠端連線資料的。為了禁止該功能,啟動skip-networking,不監聽sql的任何TCP/IP的連線,切斷遠端訪問的權利,保證安全性。假如需要遠端管理資料庫,可透過安裝PhpMyadmin來實現。假如確實需要遠端連線資料庫,至少修改預設的監聽埠,同時新增防火牆規則,只允許可信任的網路的mysql監聽埠的資料透過。

# vi /etc/my.cf
將#skip-networking註釋去掉。
# /usr/local/mysql/bin/mysqladmin -u root -p shutdown //停止資料庫
#/usr/local/mysql/bin/mysqld_safe --user=mysql & //後臺用mysql使用者啟動mysql

7、限制連線使用者的數量
資料庫的某使用者多次遠端連線,會導致效能的下降和影響其他使用者的操作,有必要對其進行限制。可以透過限制單個賬戶允許的連線數量來實現,設定my.cnf檔案的mysqld中的max_user_connections變數來完成。GRANT語句也可以支援 資源控制選項來限制伺服器對一個賬戶允許的使用範圍。

#vi /etc/my.cnf
[mysqld]
max_user_connections 2

8、使用者目錄許可權限制
預設的mysql是安裝在/usr/local/mysql,而對應的資料庫檔案在/usr/local/mysql/var目錄下,因此,必須保證該目錄不能讓未經授權的使用者訪問後把資料庫打包複製走了,所以要限制對該目錄的訪問。確保mysqld執行時,只使用對資料庫目錄具有讀或寫許可權的linux使用者來執行。
# chown -R root  /usr/local/mysql/  //mysql主目錄給root
# chown -R mysql.mysql /usr/local/mysql/var //確保資料庫目錄許可權所屬mysql使用者

9、命令歷史記錄保護
資料庫相關的shell操作命令都會分別記錄在.bash_history,如果這些檔案不慎被讀取,會導致資料庫密碼和資料庫結構等資訊洩露,而登陸資料庫後的操作將記錄在.mysql_history檔案中,如果使用update表資訊來修改資料庫使用者密碼的話,也會被讀取密碼,因此需要刪除這兩個檔案,同時在進行登陸或備份資料庫等與密碼相關操作時,應該使用-p引數加入提示輸入密碼後,隱式輸入密碼,建議將以上檔案置空。

# rm .bash_history .mysql_history  //刪除歷史記錄
# ln -s /dev/null .bash_history   //將shell記錄檔案置空
# ln -s /dev/null .mysql_history  //將mysql記錄檔案置空

10、禁止MySQL對本地檔案存取
在mysql中,提供對本地檔案的讀取,使用的是load data local infile命令,預設在5.0版本中,該選項是預設開啟的,該操作令會利用MySQL把本地檔案讀到資料庫中,然後使用者就可以非法獲取敏感資訊了,假如你不需要讀取本地檔案,請務必關閉。

測試:首先在測試資料庫下建立sqlfile.txt檔案,用逗號隔開各個欄位
# vi sqlfile.txt 
1,sszng,111
2,sman,222
#mysql> load data local infile 'sqlfile.txt' into table users fields terminated by ','; //讀入資料
#mysql> select * from users;
+--------+------------+----------+
| userid  | username   | password |
+--------+------------+----------+
|      1 | sszng    | 111   | 
|      2 | sman    | 222  | 
+--------+------------+----------+  

成功的將本地資料插入資料中,此時應該禁止MySQL中用"LOAD DATA LOCAL INFILE"命令。網路上流傳的一些攻擊方法中就有用它LOAD DATA LOCAL INFILE的,同時它也是很多新發現的SQL Injection攻擊利用的手段!駭客還能透過使用LOAD DATALOCAL INFILE裝載"/etc/passwd"進一個資料庫表,然後能用SELECT顯示它,這個操作對伺服器的安全來說,是致命的。可以在my.cnf中新增local-infile=0,或者加引數local-infile=0啟動mysql。

#/usr/local/mysql/bin/mysqld_safe --user=mysql --local-infile=0 &
#mysql> load data local infile 'sqlfile.txt' into table users fields terminated by ',';
#ERROR 1148 (42000): The used command is not allowed with this MySQL version

--local-infile=0選項啟動mysqld從伺服器端禁用所有LOAD DATA LOCAL命令,假如需要獲取本地檔案,需要開啟,但是建議關閉。

11、MySQL伺服器許可權控制
MySQL許可權系統的主要功能是證實連線到一臺給定主機的使用者,並且賦予該使用者在資料庫上的SELECT、INSERT、UPDATE和DELETE等許可權(詳見user超級使用者表)。它的附加的功能包括有匿名的使用者並對於MySQL特定的功能例如LOAD DATA INFILE進行授權及管理操作的能力。

管理員可以對user,db,host等表進行配置,來控制使用者的訪問許可權,而user表許可權是超級使用者許可權。只把user表的許可權授予超級使用者如伺服器或資料庫主管是明智的。對其他使用者,你應該把在user表中的許可權設成'N'並且僅在特定資料庫的基礎上授權。你可以為特定的資料庫、表或列授權,FILE許可權給予你用LOAD DATA INFILE和SELECT ... INTO OUTFILE語句讀和寫伺服器上的檔案,任何被授予FILE許可權的使用者都能讀或寫MySQL伺服器能讀或寫的任何檔案。(說明使用者可以讀任何資料庫目錄下的檔案,因為伺服器可以訪問這些檔案)。 FILE許可權允許使用者在MySQL伺服器具有寫許可權的目錄下建立新檔案,但不能覆蓋已有檔案在user表的File_priv設定Y或N。,所以當你不需要對伺服器檔案讀取時,請關閉該許可權。

#mysql> load data infile 'sqlfile.txt' into table loadfile.users fields terminated by ','; 
Query OK, 4 rows affected (0.00 sec) //讀取本地資訊sqlfile.txt'
Records: 4  Deleted: 0  Skipped: 0  Warnings: 0
#mysql> update user set File_priv='N' where user='root'; //禁止讀取許可權
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql> flush privileges; //重新整理授權表
Query OK, 0 rows affected (0.00 sec)
#mysql> load data infile 'sqlfile.txt' into table users fields terminated by ','; //重登陸讀取檔案
#ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) //失敗
# mysql> select * from loadfile.users into outfile 'test.txt' fields terminated by ',';
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
為了安全起見,隨時使用SHOW GRANTS語句檢查檢視誰已經訪問了什麼。然後使用REVOKE語句刪除不再需要的許可權。

12、使用chroot方式來控制MySQL的執行目錄
Chroot是linux中的一種系統高階保護手段,它的建立會將其與主系統幾乎完全隔離,也就是說,一旦遭到什麼問題,也不會危及到正在執行的主系統。這是一個非常有效的辦法,特別是在配置網路服務程式的時候。

13、關閉對Web訪問的支援
如果不打算讓Web訪問使用MySQL資料庫,沒有提供諸如PHP這樣的Web語言的時候,重新設定或編譯你的PHP,取消它們對MySQL的預設支援。假如伺服器中使用php等web程式,試試用Web形式非法的請求,如果得到任何形式的MySQL錯誤,立即分析原因,及時修改Web程式,堵住漏洞,防止MySQL暴露在web面前。
對於Web的安全檢查,在MySQL官方文件中這麼建議,對於web應用,至少檢查以下清單:
    試試用Web形式輸入單引號和雙引號('''和'"')。如果得到任何形式的MySQL錯誤,立即分析原因。
    試試修改動態URL,可以在其中新增%22('"')、%23('#')和%27(''')。
    試試在動態URL中修改資料型別,使用前面示例中的字元,包括數字和字元型別。你的應用程式應足夠安全,可以防範此類修改和類似攻擊。
    試試輸入字元、空格和特殊符號,不要輸入數值欄位的數字。你的應用程式應在將它們傳遞到MySQL之前將它們刪除或生成錯誤。將未經過檢查的值傳遞給MySQL是很危險的!
    將資料傳給MySQL之前先檢查其大小。
    用管理賬戶之外的使用者名稱將應用程式連線到資料庫。不要給應用程式任何不需要的訪問許可權。

14、資料庫備份策略
一般可採用本地備份和網路備份的形式,可採用MySQL本身自帶的mysqldump的方式和直接複製備份形式,

直接複製資料檔案最為直接、快速、方便,但缺點是基本上不能實現增量備份。為了保證資料的一致性,需要在備份檔案前,執行以下 SQL 語句:FLUSH TABLES WITH READ LOCK;也就是把記憶體中的資料都重新整理到磁碟中,同時鎖定資料表,以保證複製過程中不會有新的資料寫入。這種方法備份出來的資料恢復也很簡單,直接複製回原來的資料庫目錄下即可。

使用mysqldump可以把整個資料庫裝載到一個單獨的文字檔案中。這個檔案包含有所有重建您的資料庫所需要的SQL命令。這個命令取得所有的模式(Schema,後面有解釋)並且將其轉換成DDL語法(CREATE語句,即資料庫定義語句),取得所有的資料,並且從這些資料中建立INSERT語句。這個工具將您的資料庫中所有的設計倒轉。因為所有的東西都被包含到了一個文字檔案中。這個文字檔案可以用一個簡單的批處理和一個合適SQL語句導回到MySQL中。

使用 mysqldump進行備份非常簡單,如果要備份資料庫" nagios_db_backup ",使用命令,同時使用管道gzip命令對備份檔案進行壓縮,建議使用異地備份的形式,可以採用Rsync等方式,將備份伺服器的目錄掛載到資料庫伺服器,將資料庫檔案備份打包在,透過crontab定時備份資料:

#!/bin/sh
time=`date +"("%F")"%R`
$/usr/local/mysql/bin/mysqldump -u nagios -pnagios nagios | gzip >/home/sszheng/nfs58/nagiosbackup/nagios_backup.$time.gz
# crontab -l
# m h  dom mon dow   command
00 00 * * * /home/sszheng/shnagios/backup.sh

恢復資料使用命令:
gzip -d nagios_backup.\(2008-01-24\)00\:00.gz
nagios_backup.(2008-01-24)00:00
#mysql -u root -p nagios      


三、Mysqld安全相關啟動選項
下列mysqld選項影響安全:
    --allow-suspicious-udfs
該選項控制是否可以載入主函式只有xxx符的使用者定義函式。預設情況下,該選項被關閉,並且只能載入至少有輔助符的UDF。這樣可以防止從未包含合法UDF的共享物件檔案載入函式。
    --local-infile[={0|1}]
如果用--local-infile=0啟動伺服器,則客戶端不能使用LOCAL in LOAD DATA語句。
    --old-passwords
強制伺服器為新密碼生成短(pre-4.1)密碼雜湊。當伺服器必須支援舊版本客戶端程式時,為了保證相容性這很有用。
     (OBSOLETE) --safe-show-database
在以前版本的MySQL中,該選項使SHOW DATABASES語句只顯示使用者具有部分許可權的資料庫名。在MySQL 5.1中,該選項不再作為現在的 預設行為使用,有一個SHOW DATABASES許可權可以用來控制每個賬戶對資料庫名的訪問。
    --safe-user-create
如果啟用,使用者不能用GRANT語句建立新使用者,除非使用者有mysql.user表的INSERT許可權。如果你想讓使用者具有授權許可權來建立新使用者,你應給使用者授予下面的許可權:
mysql> GRANT INSERT(user) ON mysql.user TO 'user_name'@'host_name';
這樣確保使用者不能直接更改許可權列,必須使用GRANT語句給其它使用者授予該許可權。
    --secure-auth
不允許鑑定有舊(pre-4.1)密碼的賬戶。
    --skip-grant-tables
這個選項導致伺服器根本不使用許可權系統。這給每個人以完全訪問所有的資料庫的權力!(透過執行mysqladmin flush-privileges或mysqladmin eload命令,或執行FLUSH PRIVILEGES語句,你能告訴一個正在執行的伺服器再次開始使用授權表。)
    --skip-name-resolve
主機名不被解析。所有在授權表的Host的列值必須是IP號或localhost。
    --skip-networking
在網路上不允許TCP/IP連線。所有到mysqld的連線必須經由Unix套接字進行。
    -skip-show-database
使用該選項,只允許有SHOW DATABASES許可權的使用者執行SHOW DATABASES語句,該語句顯示所有資料庫名。不使用該選項,允許所有使用者執行SHOW DATABASES,但只顯示使用者有SHOW DATABASES許可權或部分資料庫許可權的資料庫名。請注意全域性許可權指資料庫的許可權。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15747463/viewspace-742146/,如需轉載,請註明出處,否則將追究法律責任。

相關文章