MySQL安全措施
数据库作为数据管理的平台,它的安全性首先由系统内部和网络安全两部分来决定的。对于系统管理员来说,首先要保证系统本身的安全,在安装MySQL数据时,需要对基础环境进行较好的配置。
一、修改root用户口令
缺省安装的MySQL的root用户是空密码的,为了安全起见,必须修改为强密码,所谓的强密码,至少8位,由字母、数字和符号组成的不规律密码。使用MySQL自带的命令 mysqladmin修改root密码,同时也可以登陆数据库,修改数据库mysql下的user表的字段内:
mysql> update mysql.user set password=password('upassword') where user='root';
mysql> flush privileges;
二、删除默认数据库和数据库用户
一般情况下,MySQL 数据库安装在本地,并且也只需要本地的 php 脚本对 mysql 进行读取,所以很多用户不需要,尤其是默认安装的用户。
MySQL 初始化后会自动生成空用户和test库,进行安装的测试,这会对数据库的安全构成威胁,有必要全部删除,最后的状态只保留单个root即可,当然以后根据需要增加用户和数据库:
# 删除数据库 test
drop database test;
# 删除存放在数据库的表信息,因为还没有数据库信息
mysql> delete from mysql.db;
mysql> delete from mysql.user where not (user='root');
mysql> delete from mysql.user where user='root' and password='';
mysql> flush privileges;
三、改变默认 MySQL 管理员账号
系统MySQL的管理员名称是root,而一般情况下,数据库管理员都没进行修改,这一定程度上对系统用户穷举的恶意行为提供了便利,此时修改为复杂的用户名,请不要在设定为admin或者administraror的形式,因为它们也在易猜的用户字典中。
mysql> update mysql.user set user="newroot" where user="root";
flush privileges;
四、关于密码的管理
密码是数据库安全管理的一个很重要因素,不要将纯文本密码保存到数据库中。如果你的计算机有安全危险,入侵者可以获得所有的密码并使用它们。相反,应使用 MD5()、SHA1() 或单向哈希函数。
也不要从词典中选择密码,有专门的程序可以破解它们,请选用至少八位,由字母、数字和符号组成的强密码。
在存取密码时,使用mysql的内置函数password()的sql语句,对密码进行加密后存储。
例如以下方式在users表中加入新用户:
mysql> insert into users values (1,password(1234),'test');
五、使用独立用户运行MySQL
绝对不要作为使用root用户运行MySQL服务器。这样做非常危险,因为任何具有FILE权限的用户能够用root创建文件(例如:~root/.bashrc)。
mysqld拒绝使用 root 运行,除非使用-user=root选项明显指定。应该用普通非特权用户运行mysqld。要想用其它Unix用户启动mysqld,增加user选项指定/etc/my.cnf选项文件或服务器数据目录的my.cnf选项文件中的[mysqld]组的用户名:
/etc/my.cnf 配置文件中:
[mysqld]
user=mysql
然后重启MySQL服务。
无论你手动启动或通过mysqld_safe或mysql.server 启动,都能确保使用mysql的身份。也可以在启动数据库是,加上user参数:
/usr/bin/mysqld_safe --user=mysql
作为其它linux用户而不用root 运行mysqld,你不需要更改user表中的root用户名,因为MySQL账户的用户名与linux账户的用户名无关。确保mysqld运行时,只使用对数据库目录具有读或写权限的linux用户来运行。
六、禁止远程连接数据库
在命令行netstat -ant下看到,默认的3306端口是打开的,此时打开了mysqld的网络监听,允许用户远程通过帐号密码连接数本地据库,默认情况是允许远程连接数据的。为了禁止该功能,启动skip-networking,不监听sql的任何TCP/IP的连接,切断远程访问的权利,保证安全性。
假如需要远程管理数据库,可通过安装PhpMyadmin来实现(大公司不推荐)。如果确实需要远程连接数据库,至少修改默认的监听端口,同时添加防火墙规则,只允许可信任的网络的mysql监听端口的数据通过。
编辑 /etc/my.cnf,加入如下语句
[mysqld]
skip-networking
然后重启MySQL服务。
七、限制连接用户的数量
数据库的某用户多次远程连接,会导致性能的下降和影响其他用户的操作,有必要对其进行限制。
可以通过限制单个账户允许的连接数量来实现,设置my.cnf文件的mysqld中的 max_user_connections变量来完成。GRANT语句也可以支持资源控制选项来限制服务器对一个账户允许的使用范围。
编辑 /etc/my.cnf,加入如下语句:
[mysqld]
max_user_connections 2
八、命令历史记录保护
数据库相关的 shell 操作命令都会分别记录在.bash_history,如果这些文件不慎被读取,会导致数据库密码和数据库结构等信息泄露,而登陆数据库后的操作将记录在/etc/my.cnf 文件配置的文件中,如果使用update表信息来修改数据库用户密码的话,也会被读取密码,因此需要删除这两个文件。
同时在进行登陆或备份数据库等与密码相关操作时,应该使用-p参数加入提示输入密码后,隐式输入密码,建议将以上文件置空。
配置文件/etc/my.cnf中配置数据库操作日志存放路径:
[mysqld_safe]
log=~/.mysql_history
删除操作命令历史:
rm .bash_history .mysql_history
ln -s /dev/null .mysql_history
九、SQL 攻击
一些心怀不轨的人使用load data local infile获取 /etc/passwd文件内容步骤:
mysql> create database test;
Query OK, 1 row affected (0.00 sec)
mysql> use test
Database changed
mysql> create table passwd (
-> a varchar(255),
-> b varchar(255),
-> c varchar(255),
-> d varchar(255),
-> e varchar(255),
-> f varchar(255),
-> g varchar(255)
-> );
Query OK, 0 rows affected (0.01 sec)
mysql> load data local infile '/etc/passwd' into table test.passwd fields terminated by ':';
然后执行:
mysql> select * from test.passwd;
mysql> mysql> select * from test.passwd;
+-----------+------+-------+-------+-----------+------------------+----------------+
| a | b | c | d | e | f | g |
+-----------+------+-------+-------+-----------+------------------+----------------+
| root | x | 0 | 0 | root | /root | /bin/bash |
| bin | x | 1 | 1 | bin | /bin | /sbin/nologin |
| daemon | x | 2 | 2 | daemon | /sbin | /sbin/nologin |
| adm | x | 3 | 4 | adm | /var/adm | /sbin/nologin |
| lp | x | 4 | 7 | lp | /var/spool/lpd | /sbin/nologin |
| sync | x | 5 | 0 | sync | /sbin | /bin/sync |
| shutdown | x | 6 | 0 | shutdown | /sbin | /sbin/shutdown |
| halt | x | 7 | 0 | halt | /sbin | /sbin/halt |
| mail | x | 8 | 12 | mail | /var/spool/mail | /sbin/nologin |
| operator | x | 11 | 0 | operator | /root | /sbin/nologin |
| games | x | 12 | 100 | games | /usr/games | /sbin/nologin |
| ftp | x | 14 | 50 | FTP User | /var/ftp | /sbin/nologin |
+-----------+------+-------+-----省略一些信息---+------------------+----------------+
36 rows in set (0.00 sec)
编辑 /etc/my.cnf 文件,在[mysqld]下加入如下语句:
[mysqld]
local-infile=0
或者直接执行命令:
mysql_safe --user=mysql --local-infile=0
将test删除后,再次执行load data local infile命令,导入/etc/passwd内容,发现命令出错:
mysql> load data local infile '/etc/passwd' into table test.passwd fields terminated by ':';
ERROR 1148 (42000): The used command is not allowed with this MySQL version
将test删除:
mysql> drop database test;
Query OK, 1 row affected (0.01 sec)