1年前的文章,不知道现在还有用没...
最近事情多了,很多技术性的东西不太愿意深究了.过几天写点solaris企业性能的文章来
加固你的mysql
前言:mysql已经成为当前网络中使用最多的数据库之一,特别是在web应用上,它已经占据了中小型应用的绝对优势。这一切都源于它的小巧,它的简单有效的安全机制,它的易用性,它的开放式许可,它的多平台,更主要的是它与三大web语言之一的php之间的完美结合。
但不幸的是,一个缺省安全的mysql,由于root密码为空,已经程序漏洞,导致被溢出,导致安装mysql的服务器成为一个被经常攻击的对象。更严重的是,常导致被攻击之后数据库被破坏,造成灾难性的后果。下面就将带你进入为了保卫数据而进行的保卫战中来。
1.1 系统环境
一台redhat9自定义安装的服务器,系统安装了gcc,以及一些其他要求的软件包,比如apache,php等。安装完系统后的第一件事就是升级系统的软件包。作为web服务器,系统接受php脚本的请求,php使用下面安装的mysql数据库作为动态发布的接触。
1.2 安全要求:
① mysql运行在一个独立的(chroot)环境下;
② mysqld进程运行于一个独立的用户/用户组下,此用户和用户组没有根目录,没有shell,也不能用于其他程序;
③ mysql的root帐号要被改名和修改一个复杂的密码;
④ 只允许本地连接mysql,网络连接被启动mysql的时候禁止掉;
⑤ 确实连接mysql的nobody帐号登陆被禁止;
⑥ test数据库被删除。
2.1 Mysql的安装准备
安装mysql之前,我们按照上面要求需要创建一个用于启动mysql的用户和组。
#groupadd mysql
#useradd mysql –C “start mysqld’s account” –d /dev/null –g mysql –s /sbin/nologin
2.2 编译和安装
下载mysql源代码包:
wget http://mysql.linuxaid.com.cn/Dow ... ysql-3.23.52.tar.gz
解压缩:
tar –zxvf mysql-3.23.52.tar.gz
一般我们把mysql安装在/usr/local/mysql下面,如果你有自己的特殊设置,请自己注意调整,不过由于后面我们将chrooting,那样作没太大的必要,你到时候只是使用这里的客户工具而已,比如mysql,mysqladmin,mysqldump等。废话少说,开始编译安装吧。
#./configure --prefix=/usr/local/mysql \
--with-mysqld-user=mysql \
--with-unix-socket-path=/tmp/mysql.sock \
--with-mysqld-ldflags=-all-static
#make && make install
#strip /usr/local/mysql/libexec/mysqld
#scripts/mysql_install_db
#chown -R root /usr/local/mysql
#chown -R mysql /usr/local/mysql/var
#chgrp -R mysql /usr/local/mysql
上面的步骤的具体作用在mysql手册里边已经有了介绍,唯一需要解释的和一般的步骤不同之处在于--with-mysqld-ldflags=-all-static。记得我们前面要求的地方吧!我们需要用到chroot环境,而mysql本身连接成静态后,就不用我们再创建一些库环境了。
2.3 配置并启动mysql
mysql的配置文件需要我们手工选择拷贝几个模板文件中的一个到/etc下,这几个模板文件位于源文件的support-files目录,一共4个(small,medium,large,huge).
#cp support-files/my-medium.cnf /etc/my.cnf
#chown root:sys /etc/my.cnf
#chmod 644 /etc/my.cnf
启动mysql,注意使用用户为mysql
#/usr/local/mysq/bin/safe_mysqld --user=mysql &
2.4 测试
为了测试安装的程序是否正确,以及mysql是否已经启动正常,最好的办法就是用mysql客户端来连接数据库。
#/usr/local/mysql/bin/mysql
[root@ftp bin]# mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 687 to server version: 3.23.58
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
mysql> show databases;
+--------------+
| Database |
+--------------+
| mysql |
| test |
+--------------+
2 rows in set (0.07 sec)
mysql>quit
连接成功,可以关闭数据库了:
#/usr/local/mysql/bin/mysqladmin –uroot shutdown
如果连接失败了呢,我们该怎么办?这个时候需要仔细分析出错原因。
#more /usr/local/mysql/var/`hostname`.err
3.1 chrooting环境
chroot是unix/类unix的一种手段,它的建立会将其与主系统几乎完全隔离,也就是说,一旦其遭到了什么问题,它也不会危及到正在的主系统。这是一个非常有效的办法,特别是在配置网络服务程序的时候。
3.2 chroot的准确工作
首先,应当建立如下目录结构
|--- /dev
| /etc
/chroot/mysql--- | /tmp
| /var/tmp |-- /libexec
|---- /local/mysql --- | /share/mysql/english
#mkdir –p /chroot/mysql/dev
# mkdir -p /chroot/mysql/etc
#mkdir -p /chroot/mysql/tmp
#mkdir -p /chroot/mysql/var/tmp
#mkdir -p /chroot/mysql/usr/local/mysql/libexec
#mkdir -p /chroot/mysql/usr/local/mysql/share/mysql/english
然后设定好目录权限
#chown -R root:sys /chroot/mysql
#chmod -R 755 /chroot/mysql
#chmod 1777 /chroot/mysql/tmp
3.3 拷贝mysql的程序和文件到chroot下
#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/passwd /chroot/mysql/etc/passwd
#cp /etc/my.cnf /chroot/mysql/etc/
3.4 编辑chroot下的passwd文件和group文件
#vi /chroot/etc/passwd
删除除了mysql的所有行
#vi /chroot/etc/group
删除除了mysql的所有行
3.5 创建特殊的设备文件/dev/null
参照系统的样子作就可以
#ls –al /dev/null
crw-rw-rw- 1 root root 1, 3 Jan 30 2003 /dev/null
#mknod /chroot/mysql/dev/null c 2 2
chown root:root /chroot/mysql/dev/null
chmod 666 /chroot/mysql/dev/null
3.6 拷贝mysql的数据库文件到chroot下
#cp -R /usr/local/mysql/var/ /chroot/mysql/usr/local/mysql/var
#chown -R mysql:mysql /chroot/mysql/usr/local/mysql/var
3.7 安装chrootuid程序
下载chrootuid
wget http://www.mirrors.wiretapped.ne ... chrootuid1.3.tar.gz
然后解压,然后编译,最后cp到/usr/bin目录。
3.8 测试chroot环境下的mysql配置
chrootuid /chroot/mysql mysql /usr/local/mysql/libexec/mysqld &
3.9 测试连接如chroot下的mysql
#/usr/local/mysql/bin/mysql –socket=/chroot/mysql/tmp/mysql.sock
…………..
mysql>show databases;
mysql>create database wgh;
mysql>quit;
#ls –al /chroot/mysql/var/
……………
4.0 配置服务器
为了更加安全地使用mysql,我们需要对mysql地数据库进行安全配置。并且由于chroot的愿意,我们的配置文件也要有些不同之处。
4.1 关闭远程连接
首先,应该关闭3306端口,这是MySQL的默认监听端口。由于我们的MySQL只服务于本地教本,不需要远程连接。尽管MySQL内建的安全机制已经很严格了,但监听一个tcp端口仍然是危险的行为,因为如果MySQL程序本身有问题的话,那么未授权的访问可以绕过MySQL的内建安全机制。关闭网络监听的方法很简单,在/chroot/mysql/etc/my.cnf文件中[mysqld]部分,加上skip-networking即可。
那么关闭了网络,本地程序是怎么连接MySQL数据库的呢?
本地程序通过mysql.sock来连接,速度比网络连接快很多。后面会提到关于mysql.sock的具体情况。MySQL 的备份通常使用ssh来执行!
4.2 禁止MySQL导入本地文件
下面,我们将禁止MySQL中用” LOAD DATA LOCAL INFILE”命令。我记得网络上流传的一些攻击方法中就有用它!这个命令会利用mysql来读本地文件到数据库中,然后用户就可以非法获取敏感信息了。这个也是很多新发现的SQL Injection攻击利用的手段!
为了禁止上述命令,在/chroot/mysql/etc/my.cnf文件的[mysqld]部分加入: set-variable=local-infile=0
为了管理方便,我们一般在系统中用的MySQL管理命令mysql,mysqladmin,mysqldump等,他们使用的是系统的/etc/my.cnf文件,如果要连接,它会寻找/tmp/mysql.sock文件,试图连接MySQL服务器,但是我们这里要连接的是chroot下的MySQL服务器,解决办法有两个:
一个就是在管理命令后面加入—socket=/chroot/mysql/tmp/mysql.sock
例如:#/usr/local/mysql/bin/mysql –root –p --socket=/chroot/mysql/tmp/mysql.sock
第二个就是在/etc/my.cnf的[client]部分加入socket=/chroot/mysql/tmp/mysql.sock
显然,第二个方便多了。
4.3 修改MySQL的root用户ID和密码
#chrootuid /chroot/mysql mysql /usr/local/mysql/libexec/mysqld &
#/usr/local/mysql/bin/mysql –uroot
……………
mysql>SET PASSWORD FOR root@localhost=PASSWORD('new_password');
尽量养成在mysql下输入密码的习惯,以为如果shell下面输入的时候可能让其他人看见。
mysql>update user set user="wghgreat" where user="root";
修改一个不容易猜的ID
mysql>flush privileges;
4.4 删除历史命令记录
这些历史文件包括~/.bash_history ~/.mysql_history等,如果你打开他们,你会大吃一惊,怎么居然有一些明文的密码在这里?!
#cat /dev/null > ~/.bash_history
#cat /dev/null > ~/.mysql_history
5 PHP和MySQL通信
默认情况下,php会通过/tmp/mysql.sock奈何MySQL通信,但这里有一个大问题,就是MySQL根本不是生成的它,而是生成的/chroot/mysql/tmp/mysql.sock,解决办法就是做一个连接 #ln /chroot/mysql/tmp/mysql.sock /tmp/mysql.sock
注意:由于hard links不能在文件系统的分区之间做,这个地方的连接必须位于同一分区内部!
6 自启动配置
在配置它之前先提示一点,即用于php的数据库需要用一个新建的帐号,其上有数据库权限设置,比如(FILE,GRANT,ACTER,SHOW DATABASE, RELOAD, SHUTDOWN, PROCESS, SUPER等)。
自启动教本示例
#!/bin/sh
CHROOT_MYSQL=/chroot/mysql
SOCKET=/tmp/mysql.sock
MYSQLD=/usr/local/mysql/libexec/mysqld
PIDFILE=/usr/local/mysql/var/`hostname`.pid
CHROOTUID=/usr/bin/chrootuid
echo -n " mysql"
case "$1" in
start)
rm -rf ${SOCKET}
nohup ${CHROOTUID} ${CHROOT_MYSQL} mysql ${MYSQLD} >/dev/null 2>&1 &
sleep 5 && ln ${CHROOT_MYSQL}/${SOCKET} ${SOCKET}
;;
stop)
kill `cat ${CHROOT_MYSQL}/${PIDFILE}`
rm -rf ${CHROOT_MYSQL}/${SOCKET}
;;
*)
echo ""
echo "Usage: `basename $0` {start|stop}" >&2
exit 64
;;
esac
exit 0
文件位于/etc/rc.d/init.d下,名为mysqld,注意要可执行!
#chmod +x /etc/rc.d/init.d/mysqld
结论:尽管我们不能做到100%的安全,但是这些措施可以保护我们的系统更加安全!
参考资料:Artur Maj的《Securing MySQL》
xuzhikun的《MySQL数据库安全配置》一文
晏子翻译的《MySQL中文参考手册》 |