top
Loading...
教你一步一步地加強MySQL的安全性

本文的實驗都假設PHP模塊已經安裝在了Apache Web服務器上了,并且被放在了目錄 /chroot/httpd下。除此以外,我們還作了如下的假設:

MySQL數據庫僅被同主機上的PHP使用;

默認的管理工具像mysqladmin、mysql和 mysqldump,被用來管理數據庫。另外,遠程的數據備份將使用SSH協議執行。

為了獲得更高的安全性能,對于MySQL的安裝和配置,應該與以下的安全要求相符合:

1) MySQL數據庫應該在被改變了默認根目錄的環境下運行;

2) MySQL進程必須使用一個在系統進程中唯一的UID/GID;

3) 對MySQL的訪問僅限于本地;

4) 保證MySQL根賬戶的密碼不易被猜測;

5) 禁止對數據庫的匿名訪問;

6) 刪除系統自帶的所有的示例數據庫和表;

安裝MySQL

在我們開始加強MySQL的安全性之前,必須在服務器上安裝它。我們在操作系統上來創建一個組和用戶帳號,并使之唯一,使之與MySQL數據庫相關聯,方法如下:

pw groupadd mysqlpw useradd mysql -c "MySQL Server" -d /dev/null -g mysql -s /sbin/nologin

1.編譯MySQL

我們先來在目錄/usr/local/mysql下編譯和安裝MySQL軟件:

./configure --prefix=/usr/local/mysql --with-mysqld-user=mysql --with-unix-socket-path=/tmp/mysql.sock --with-mysqld-ldflags=-all-staticmakesumake installstrip /usr/local/mysql/libexec/mysqldscripts/mysql_install_dbchown -R root /usr/local/mysqlchown -R mysql /usr/local/mysql/varchgrp -R mysql /usr/local/mysql

總的來說,在Apache服務器上安裝MySQL的過程基本上與手動安裝等同。可能唯一的不同點就是使用了一些參數而已,像指定了./configure行。這里最重要的不同點在于參數“--with-mysqld-ldflags=-all-static”的使用,它可以使MySQL服務器使用靜態連接。就像在第三部分涉及到的其他參數一樣,這將顯著簡化改變服務器的根路徑的過程,它們通知make程序安裝在目錄/usr/local/mysql下,以mysql賬戶的權限運行MySQL的后臺程序,并且在/tmp目錄下創建mysql.sock套接字。

2.拷貝配置文件

在執行了上面的命令后,我們還必須拷貝默認的配置文件以與期望的數據庫大小一致。例如:

cp support-files/my-medium.cnf /etc/my.cnfchown root:sys /etc/my.cnfchmod 644 /etc/my.cnf

3.啟動服務器

到這里為止,MySQL已經完全安裝了,并且整裝待發了。我們可以通過執行下面的命令來啟動MySQL的服務器:

/usr/local/mysql/bin/mysqld_safe &

4.測試連接

嘗試與一個數據庫建立連接:

/usr/local/mysql/bin/mysql -u root mysql

如果連接成功,系統將顯示如下內容:

Welcome to the MySQL monitor. Commands end with ; or g.Your MySQL connection id is 2 to server version: 4.0.13-logType 'help;' or 'h' for help. Type 'c' to clear the buffer.

然后,我們就可以看看本機上有哪些數據庫,如下所示:

mysql> show databases;+----------+| Database |+----------+| mysql || test |+----------+

2 rows in set (0.00 sec)

然后退出當前命令,使用如下命令:

mysql> quit;

一旦連接成功建立,我們就可以通過如下命令關閉數據庫:

/usr/local/mysql/bin/mysqladmin -u root shutdown

如果不這樣做,我們就應該分析一下存儲在 /usr/local/mysql/var/`hostname`.err日志文件中的信息的安全性,以消除導致問題的因素。

改變服務器的默認根目錄

接下來的第一步就是準備chrooted環境,以使MySQL服務能夠運行。這里的目標操作系統是FreeBSD4.7。然而,本文中所講授的方法同樣適用于大多數的UNIX和類似UNIX的系統。

1.準備chroot環境

為了準備chrooted環境,我們必須創建如下的目錄:

mkdir -p /chroot/mysql/devmkdir -p /chroot/mysql/etcmkdir -p /chroot/mysql/tmpmkdir -p /chroot/mysql/var/tmpmkdir -p /chroot/mysql/usr/local/mysql/libexecmkdir -p /chroot/mysql/usr/local/mysql/share/mysql/english

2.設置訪問權利

上面對目錄的訪問權利應該如下設置:

chown -R root:sys /chroot/mysqlchmod -R 755 /chroot/mysqlchmod 1777 /chroot/mysql/tmp

3.創建目錄結構

接下來,下面的這些文件應該拷貝到新的目錄中:

cp /usr/local/mysql/libexec/mysqld /chroot/mysql/usr/local/mysql/libexec/cp /usr/local/mysql/share/mysql/english/errmsg.sys/ chroot/mysql/usr/local/mysql/share/mysql/english/cp /etc/hosts /chroot/mysql/etc/cp /etc/host.conf /chroot/mysql/etc/cp /etc/resolv.conf /chroot/mysql/etc/cp /etc/group /chroot/mysql/etc/cp /etc/master.passwd /chroot/mysql/etc/passwordscp /etc/my.cnf /chroot/mysql/etc/

4.強化密碼和組

我們必須從文件/chroot/mysql/etc/passwords和/chroot/mysql/etc/group里刪除除了賬戶和組以外的行,接下來,還應該按照如下方法build密碼數據庫:

cd /chroot/mysql/etcpwd_mkdb -d /chroot/mysql/etc passwordsrm -rf /chroot/mysql/etc/master.passwd

5.特殊考慮

在Apache Web服務器上,我們還必須創建一個特殊的設備文件/dev/null:

ls -al /dev/null

系統將顯示如下的信息:

crw-rw-rw- 1 root sys 2, 2 Jun 21 18:31 /dev/null

然后,我們再使用如下的命令:

mknod /chroot/mysql/dev/null c 2 2chown root:sys /chroot/mysql/dev/nullchmod 666 /chroot/mysql/dev/null

我們還必須拷貝那些包含著在MySQL安裝過程中創建的包含授權表的mysql數據庫:

cp -R /usr/local/mysql/var/ /chroot/mysql/usr/local/mysql/varchown -R mysql:mysql /chroot/mysql/usr/local/mysql/var

6.本地化

如果主機上使用的默認語言不是英語,我們還應該拷貝合適的字符集,可以在目錄/usr/local/mysql/share/mysql/charset下找到。

7.測試配置

現在,MySQL應該可以在chrooted環境中運行了。我們可以通過下面這個命令來驗證一下它是否能正確的運行:





chrootuid /chroot/mysql mysql /usr/local/mysql/libexec/mysqld &

如果在執行了上面的命令后出現了錯誤,我們應該使用truss命令或者具有等價功能的命令如:ktrace/kdump、strace等等。這些命令可以幫助我們來找出和消除引起問題的原因。

(腳本小子:這里為了能夠運行mysqld進程,使用的是chrootuid程序而不是chroot程序,因為假設是在Apache或者PHP的環境下,它們兩個的主要不同在于chrootuid可以改變執行進程的所有者,在我們的例子里面,mysqld在一個chrooted環境下被執行的,但是進程的所有者不是root而是mysql用戶,Chrootid在許多操作系統里并不是默認安裝的,需要我們從網上下載下來,然后手動安裝上去,可以到網址[url]ftp://ftp.porcupine.org/pub/security/chrootuid1.3.tar.gz[/url]下載。)

配置服務器

接下來的步驟,我們就要來配置數據庫服務器,使之能夠適合我們的安全性要求。

在假定MySQL進行默認安裝的時候,主要的配置文件是/etc/my.cnf。然而,在我們的例子里,因為是在chrooted環境下運行服務,所以我們就要使用兩個配置文件/chroot/mysql/etc/my.cnf和/etc/my.cnf。其中,前一個可以被MySQL服務器使用,而后一個要被MySQL工具(如mysqladmin,mysql,mysqldump等)使用。

1.禁止遠程訪問

我們知道,MySQL默認情況下使用TCP的3306端口,所以,我們首先要改變一下。因為,按照我們開始的設想,數據庫僅僅是讓本機的PHP應用程序訪問,所以,我們可以將這個監聽端口的功能禁止掉。這樣就可以降低MySQL數據庫遭受直接經由TCP/IP訪問的外部主機攻擊的可能性。而同時,本地的交互還可以通過mysql.sock套接字進行。為了能夠禁止在3306端口上監聽,我們要將參數skip-networking添加到/chroot/mysql/etc/my.cnf目錄下[mysqld]部分。如果在有的時候還需要從外部訪問數據庫,可以按照如下方法使用SSH協議:

backuphost$ ssh mysqlserver /usr/local/mysql/bin/mysqldump -A > backup

2.提高本地安全性

接下來,為了防止對本地文件進行未授權的訪問,我們還需要禁止掉對LOAD DATA LOCAL INFILE命令的使用。這對于有效防止當在PHP應用程序中發現了新的SQL注入漏洞是非常有效的。這里,我們需要對在目錄/chroot/mysql/etc/my.cnf下的[mysqld]部分加一個參數set-variable=local-infile=0。

另外,為了更方便的使用數據庫管理工具,我們還必須改變/etc/my.cnf目錄[client]部分的參數設置為socket = /chroot/mysql/tmp/mysql.sock。這樣,當我們以后再需要用到管理工具的時候,就不用每次都來使用帶有socket=/chroot/mysql/tmp/mysql.sock參數的命令了。

3.改變管理員的密碼

在加強MySQL安全性的這些步驟里,改變管理員的密碼是很重要的一步,但是,這首先需要MySQL運行起來,可以通過如下命令實現:

chrootuid /chroot/mysql mysql /usr/local/mysql/libexec/mysqld &

用下面的命令改變管理員的密碼:

/usr/local/mysql/bin/mysql -u root mysql> SET PASSWORD FOR root@localhost=PASSWORD('new_password');

(腳本小子:不要直接在命令行里改變密碼,如使用“mysqladmin password”命令,因為這就有可能被同時使用服務器的其他用戶看到,從而泄漏密碼。例如:其他用戶可以使用“ps aux”命令或者查看歷史文件,就可以看到我們設置的密碼。)

4.刪除默認的數據庫和用戶

接下來,我們必須刪除示例數據庫和除了root賬戶以外的所有的賬戶,可以使用如下命令來實現:

mysql> drop database test;mysql> use mysql;mysql> delete from db;mysql> delete from user where not (host="localhost" and user="root");mysql> flush privileges;

這就可以有效阻止對數據庫的匿名連接和清除在/chroot/mysql/etc/my.cnf下的與skip-networking無關的參數,從而阻止遠程連接。

5.改變管理員的登陸名稱

我們同樣也推薦將默認管理員的賬戶名稱修改,這樣,就可以使得外部用戶很難猜測賬戶名稱。這樣一個改變,就可以有效的阻止對管理員密碼的暴力攻擊和字典攻擊。因為,攻擊者首先要猜出用戶名稱,然后才能猜測密碼。可以通過如下方式改變:

mysql> update user set user="mydbadmin" where user="root";mysql> flush privileges;

6.刪除歷史紀錄文件

最后,我們應該將MySQL中歷史文件的內容刪除,因為所有執行過的SQL命令都被以明文的形式存儲在這里,很容易泄密。這可以通過如下方式實現:

cat /dev/null > '/.mysql_history

如何在PHP和MySQL之間進行交互

因為本地的PHP與MySQL之間的交互通過/tmp/mysql.sock套接字進行,而將PHP放在chrooted環境中意味著它們之間不能交互。為了解決這個問題,在我們每次使用MySQL的時候,都必須先創建一個到PHP的chrooted環境的穩固連接。這可以通過如下命令實現:

ln /chroot/mysql/tmp/mysql.sock /chroot/httpd/tmp/

(腳本小子:/chroot/mysql/tmp/mysql.sock套接字和/chroot/httpd/tmp目錄必須處在相同的文件系統下,否則他們之間的穩固連接將不能正常工作。)

現在,我們要創建能夠被指定的PHP應用使用的所有的數據庫和賬戶,需要注意的是,這些帳戶僅僅擁有通過PHP應用對數據庫進行訪問的權利。特別需要指出的就是,這些帳戶不應該具有對mysql數據庫訪問的任何權力,當然更不用說對系統的訪問和管理特權(FILE, GRANT, ALTER, SHOW DATABASE, RELOAD, SHUTDOWN, PROCESS, SUPER 等)了。

最后,我們也應該創建一個shell腳本,用來在啟動系統的時候來運行MySQL,可以到[url]http://www.securityfocus.com/unix/images/mysql.sh[/url]上下載,而在我們的FreeBSD系統里,上面的腳本應該放在/usr/local/etc/rc.d目錄下,取名為mysql.sh。

好了,大功告成,通過上面的設置,如果有人想通過mysql入侵你的服務器,估計不死都得掉層皮,嘿嘿!

采用上面陳述的方法,我們可以顯著提高MySQL的安全性。通過在一個chrooted環境下運行數據庫,禁止掉對TCP3306端口的監聽,采用強壯的用戶密碼,我們就可以使數據庫免受大多數的攻擊。雖然沒有方法能夠使我們得到100%的安全性,但是使用描述的方法,至少可以降低來自訪問我們的Web服務的用戶的不明目的攻擊的可能性。

(T114)

作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗