数据库安全威胁

业务系统

系统漏洞

DDOS 攻击

SQL注入(高发)

自定义、自封装接口漏洞

滥用合法权限或者合法权限泄漏

业务系统攻击间接传导

业务日志泄露

请求分配不均(主要影响应用性能)

数据库自身

系统漏洞

通信协议漏洞

软件漏洞导致权限提升

弱口令

权限分配不当

审计不足,无法评估风险

大数据量带来的压力(备份时间、备份空间)

数据备份

系统漏洞

权限分配不当

隔离不足

副本不足、备份频度不够

备份数据、数据库日志泄漏

数据库安全属性

保密性

机密数据加密存储、防止内外部人员窃取和泄密

完整性

防止任何未经授权的变更、删除、越权操作等

可控制

权限控制,授权维度越细越好

可审查

日志追踪,检索未授权请求

数据库安全职责

DBA

根据对数据库的安全要求,对数据库进⾏安全加固;

当数据库出现严重漏洞时,进⾏修补;

及时发现新的安全风险,和信息安全部共同提出解决⽅案。

信息安全部门

提出对数据库的安全要求;

发现数据库的安全漏洞及时和DBA进⾏沟通,共同确认漏洞的安全风险。

数据库安全技术

加密技术

自定义加密算法

对称密钥算法

非对称密钥算法

证书加密

访问控制&身份验证

IP 授权,一般建议内网,无外网

数据库帐号和密码

数据库、数据表权限

权限范围(增、删、改、查)

密码定期更新

帐号、密码随机生成

授权记录

数据审核&追踪

关键财务数据审计,防恶意篡改

访问请求的分析

数据操作记录

审计日志

登录审核、安全审核

审核报告

和授权记录进行校对

数据备份

数据库日志备份

数据库DUMP备份

同步数据库,实时同步&延迟同步

本地备份、远程备份、异地备份

小时备份、日备份、周备份、月备份、年归档

备份服务器的安全

备份策略监控、校对、测试

数据恢复

通过同步数据库恢复

通过备份数据库恢复

恢复节点的选择

通过日志补充丢失的时间差数

日志时间点选择

MYSQL数据库加固例子

  1. 数据库存放位置检查
    ​ 数据库文件不可以存放在 /,/var,/usr目录内
    ​ 连上mysql数据,mysql -uroot -p --回车输入密码
      select @@datadir;

​ 或

      show variables where variable_name='datadir';

加固方法

​ 设置指定安全的路径

set global datadir='路径' ;

​ 或者修改配置文件my.cnf中的datadir值

datadir=‘路径’

最小权限账号运行MYSQL数据库

​ linux系统: 不是是高权限账号(root)运行mysql,也不可以是在高权限用户组内

​ ps 命令查看进程 ,grep过滤结果,使用下面命令查看运行mysql的用户

     ps -ef | grep mysql

加固方法

创建低权限账号和组

groupadd mysql -M -s /sbin/nologin

useradd -r -g mysql mysql

  1. 给新建账号添加密码
  passwd mysql

3.修改MYSQL安装目录的权限(提前关闭mysql服务)

chown -R mysl.mysql mysql安装路径

  1. 读写执行权限最小化755

chmod 755 mysql安装根路径

chmod 755 mysql安装后执行目录(bin)

chmod 755 mysql安装后lib库(libexec)

chmod -R go-rwx mysql数据存储目录(data)

5.重启mysql服务即可

   service mysqld start

禁用使用mysql命令行历史记录

查看系统中是存在.mysql_history文件:find / -name “.mysql_history” ,存在表示需要加固

加固方法

echo “export MYSQL_HISTORY=dev/null” >> /etc/profile

ln -s /dev/null .mysql_history文件路径

rm -r .mysql_history文件路径

控制慢查询日志文件的权限

查看慢查询日志文件名称和路径,然后查看权限,日志文件权限应满足:chmoed 660 和chmod mysq.mysql

如果没有开启慢查询,表示安全

第一种方法

查看慢查询日志文件名称和路径

select @@slow_query_log_file;

或者

show variables like ‘slow_query_log_file’;

查看是否开启慢查询, slow_query_log 值:ON表示开启,OFF表示关闭

show variables like ‘%query%’;

第二种方法,直接查看mysql配置文件 /etc/my.cnf

  cat /etc/my.cnf

看[mysqld]下面是否有以下配置:

logout=file

slow_query_log=on

slow_query_log_file=路径

long_query_time=2

查看慢查询日志文件的权限

 ls -l 慢查询日志文件路径

加固方法

#修改慢查询日志权限如下

​ chmod 660 慢查询日志文件

​ chmod msyql.mysql 慢查询日志文件

  1. 控制通用日志文件的权限
    查看通用日志文件名字和权限,日志文件权限应满足:chmoed 660 和chmod mysq.mysql

如果没有开启慢查询,表示安全

查看是否开始通用日志记录,如果general_log为ON表示开启,否者就是关闭,其中> > > > general_log_file是通用日志的存放位置

show variables like ‘%general%’;

show variables like ‘%general%’;

根据第一步查看获取日志文件的位置查看通用日志文件的权限

ls -l 通用日志文件

加固方法

修改权限和所属权限

chmod 660 <log file>

chown mysql:mysql <log file>

  1. 审计日志文件的权限控制
    查看 审计日志文件名字和权限,日志文件权限应满足:chmoed 660 和chmod mysq.mysql

如果没有开启慢查询,表示安全

#查看文件路径

show variables like '%audit_log_file%';

查看权限

​ ls -l 审计日志文件

加固方法

​ 修改权限和所属权限

chmod 660 <log file>

chown mysql:mysql <log file>

  1. 查看MYSQL版本,是否需要进行打补丁
show variables like 'version';

加固方法

​ 安装补丁

​ 升级到mysql 最新版本

  1. 删除test数据库
    如果存在test默认数据库,需要进行删除做加固

如果没有,就不需要加固

#1. 查看系统数据库

show databases;

加固方法

drop database test;

  1. 读取本地文件设置为OFF
    确认mysql数据库关闭对本地文件的读取功能,local_infile应为OFF
查看是否开启本地读取文件功能

show variables like ‘local_infile’

1

加固方法

临时设置

set @@local_infile=0;

永久设置,修改/etc/my.cnf 加入local-infile=0

在[mysqld]下面加入

local-infile=0

  1. 确认只有管理员权限可以管理所有表,查看所有用户和用户密码哈希,权限修改
  2. 查看所有数据库用户
select user,host from mysql.user;

​2.执行以下两条语句确保结果智能是数据库管理员

SELECT user, host FROM mysql.user WHERE (Select_priv = 'Y') OR (Insert_priv = 'Y') OR (Update_priv = 'Y')

OR (Delete_priv = 'Y') OR (Create_priv = 'Y') OR (Drop_priv = 'Y');

SELECT user, host FROM mysql.db WHERE db = 'mysql' AND ((Select_priv = 'Y') OR (Insert_priv = 'Y') OR (Update_priv = 'Y') OR (Delete_priv = 'Y') OR (Create_priv = 'Y') OR (Drop_priv = 'Y'));

加固方法

  1. 确保一个数据库使用一个用户(尽可能的每个数据库使用单独的用户)

每个用户只能对自己的库和表有全部权限,对其他库表根据情况有部分权限

2. 确保权限管理只能是管理员

授权操作 :授予xiaoming用户对数据库test的goods表privileges权限

grant privileges on test.goods to xiaoming@localhost

​ privileges:表示要授予什么权力,例如可以有 select , insert ,delete,update等,如果要授予全部权力,则填 ALL

​ atabasename.tablename:表示用户的权限能用在哪个库的哪个表中,如果想要用户的权限很作用于所有的数据库所有的表,则填 .,*是一个通配符,表示全部。

​ username@host:表示授权给哪个用户。

​ GRANT select,insert ON zje.zje TO ‘aaa’@’%’; //表示给用户aaa授权,让aaa能给zje库中的zje表 实行 insert 和 select。

​ GRANT ALL ON . TO ‘aaa’@’%’;//表示给用户aaa授权,让aaa能给所有库所有表实行所有的权力。

删除无关用户

​ drop user ‘test’@’%’; #删除 test用户

撤销用户权限

revoke privileges ON database.tablename FROM ‘username’@‘host’;

privileges,database.tablename,‘username’@'host’同上

根据实际情况对数据库用户进行权限的回收

  1. 限制非管理权限
    ​ file_priv:表示是否允许用户读取数据库所在主机的本地文件;

​ Process:表示是否允许用户查询所有用户的命令执行信息;

​ Super_priv:表示用户是否有设置全局变量、管理员调试等高级别权限;

​ Shutdown_priv:表示用户是否可以关闭数据库;

​ Create_user_priv:表示用户是否可以创建或删除其他用户;

​ Grant_priv:表示用户是否可以修改其他用户的权限;

​ 应确保只有数据库管理员才有上述权限,使用如下sql语句查看拥有各个权限的数据库账号:

  select user, host from mysql.user where File_priv = 'Y';

select user, host from mysql.user where Process_priv = 'Y';

select user, host from mysql.user where Process_priv = 'Y';

SELECT user, host FROM mysql.user WHERE Shutdown_priv = 'Y';

SELECT user, host FROM mysql.user WHERE Create_user_priv = 'Y';

SELECT user, host FROM mysql.user WHERE Grant_priv = 'Y';

SELECT user, host FROM mysql.db WHERE Grant_priv = 'Y';

加固方法

回收权限

REVOKE FILE ON *.* FROM '<user>';

REVOKE PROCESS ON *.* FROM '<user>';

REVOKE SUPER ON *.* FROM '<user>';

REVOKE SHUTDOWN ON *.* FROM '<user>';

REVOKE CREATE USER ON *.* FROM '<user>';

REVOKE GRANT OPTION ON *.* FROM <user>;

​ 其中user为上述查询到的非管理员用户。

​ 例如:回收用户xiaoming的本地文件读取权限

revoke file on *.* from 'xiaoming';

  1. 合理控制DML/DDL操作授权
    ​ DML/DDL语句包括创建或修改数据库结构的权限,例如insert、update、delete、create、drop和alter语句,在任何数据库中都要控制用户的此类权限,确保只授权给有业务需求的非管理员用户。Mysql命令行下执行如下命令:
SELECT User,Host,Db FROM mysql.db WHERE Select_priv='Y' OR Insert_priv='Y' OR Update_priv='Y' OR Delete_priv='Y' OR Create_priv='Y'

OR Drop_priv='Y' OR Alter_priv='Y';

加固方法

REVOKE SELECT ON <host>.<database> FROM <user>;

REVOKE INSERT ON <host>.<database> FROM <user>;

REVOKE UPDATE ON <host>.<database> FROM <user>;

REVOKE DELETE ON <host>.<database> FROM <user>;

REVOKE CREATE ON <host>.<database> FROM <user>;

REVOKE DROP ON <host>.<database> FROM <user>;

REVOKE ALTER ON <host>.<database> FROM <user>;

其中为查询到的未授权的用户,host为相关主机,database为相关数据库。

13. 开启错误日志审计功能

错误日志包括数据库运行和停止过程中的一系列活动信息,有助于分析数据库运行过程中的一些异常活动,一般情况下需要开启错误日志记录功能,使用如下命令查询:

show variables like 'log_error';

确保返回结果为非空,如果为空,需要在mysql数据库配置文件中增加相关配置。

加固方法

在/etc/my.cnf加入配置

[mysqld_safe]

log-error=log文件路径

  1. 确保日志存放在非系统区域
    日志文件随着数据库的运行会不断增加,如果存放在系统区域,则会影响系统的正常运行,使用如下命令进行查询:
mysql show variables like 'log_error'; 

或者直接去mysql文件查看 /etc/my.cnf log-error的值

确保返回结果不是如下路径:/、/var、/usr

加固方法

修改mysql配置文件log-error值不是 / ,/var/ ,/usr下

15. 关闭原始日志功能

原始日志选项会决定一些敏感信息是否会被明文写进日志中,例如查询日志、慢查询日志、二进制日志,确保数据库配置文件中存在如下配置项:

查看配置文件中是否有 log-raw=OFF或者log-raw=0

cat /etc/my.cnf

加固方法

修改mysql 配置文件 /etc/my.cnf 加入 log-raw=0

[mysqld_safe]

log-raw=1

  1. 用户密码加密强度
    old_passwords的值不能为0,如果为0则用户密码可被破解
select @@old_passwpords;

值为0表示需要加固,否则不需要加固

加固方法

set global old_passwords=1;

或者

set global old_passwords=2;

或者修改/etc/my.cnf 加入old_passwords=1

[mysqld_safe]

old_passords=1 #或者等于2

  1. secure_auth 选项设置
    如果客户端采用Old_passwords发起连接请求,如果服务器端设置了secure_auth,则客户端会拒绝连接请求,可以根据安全需求在配置文件中做相应配置。

查看配置文件中是否有 secure_auth 并且值不为0

cat /etc/my.cnf

加固方法

或者修改/etc/my.cnf 加入secure_auth=1

[mysqld_safe]

secure_auth=1 #或者等于2

  1. 确保所有用户都要求使用非空密码登录
    执行如下语句查询是否有用户不需要密码即可登录:
SELECT User,host FROM mysql.user WHERE (plugin IN('mysql_native_password', 'mysql_old_password') AND (LENGTH(Password) = 0 OR Password IS NULL))OR (plugin='sha256_password' AND LENGTH(authentication_string) = 0);

如果没有返回用户表示不存在

或者使用以下语句查看是否有空密码

select user,host from msyql.user;

加固方法

​ 对空口零的用户加入密码user的值指定用户, password(’’)对用户密码加密,new password指定用户的密码

update mysql.user set password=password('new password') where user='root';

  1. 数据库定时备份
    定时对数据备份,异地备份,全量备份

加固方法

创建定时任务脚本,指定时间间隔对数据备份

例子:

a.新建备份文件并赋予可以执行的权限

mkdir -p /home/mysql_backup/

touch /home/mysql_backup/mysql_backup.sh

chmod 551 /home/mysql_backup/mysql_backup.sh

b.编辑/home/mysql_backup/mysql_backup.sh

vim /home/mysql_backup/mysql_backup.sh

c.写入以下内容

 backupdir=/home/mysql_backup

time=` date +%Y_%m_%d_%H_%M_%S `

db_user=root

db_pass=123456

mysqldump --all-databases -u $db_user -p$db_pass | gzip > $backupdir/$time.sql.gz

find $backupdir -name "*.sql.gz" -type f -mtime +5 -exec rm -rf {} \; > /dev/null 2>&1

d.编辑crontab

crontab -e

e.在最后一行加入

* */1 * * * root /home/mysql_backup/mysql_backup.sh

f.重启crontab

service crond restart