1. 操作系统级别
1.1. 禁止 MySQL链接历史记录
• 建议理由 
  
• MySQL会把客户端登陆的交互执行记录保存在 .mysql_history 文件中。该记录有可能会暴露登陆过程中的敏感信息。建议删除该记录。
• 检查方法 
  
• 检查.mysql_history 文件是否存在(默认在 /home 下) 
    
• find /home -name ".mysql_history" 
• 修复建议:删除并禁止继续记录 
  
• 如果存在 .mysql_history,则删除
• 创建链接,防止.MySQL_history再次生成 
    
• ln -s /dev/null $HOME/.mysql_history 
• 或 set global mysql_history='/dev/null'
1.2. 禁止MySQL_PWD的使用
• 建议理由 
  
• MySQL_PWD是一种用于存储MySQL密码的环境变量。而且是以明文形式存储,带来了非常大的安全隐患。
• 检查方法 
  
• 检查MySQL_PWD环境变量是否存在于某个进程中 
    
• grep MySQL_PWD /proc/*/environ
• 如果有返回行说明那个进程使用了MySQL_PWD环境变量。
• 修复建议:对使用MySQL_PWD环境变量变量的脚本和进程,建议不在使用该环境变量。
1.3. 禁止MySQL操作系统账号登陆
• 建议理由 
  
• MySQL的操作做系统账号在安装完数据库后,不应该有其他用途。建议禁止该账号登陆操作系统。此举在防止黑客利用MySQL数据库漏洞反射shell有极佳效果。
• 检查方法 
  
• 假设MySQL数据库操作系统账号就是 mysql 
    
• getent passwd MySQL | egrep "^.*[ \ /bin\ / false| \ / sbin \ / nologin]$" 
• 如果没有返回行则说明存在安全隐患。
• 修复建议:执行下列语句禁止 mysql 登陆 
  
• usermod -s /sbin/nologin mysql
1.4. 禁止MySQL使用默认端口
• 建议理由 
  
• 使用默认端口,会更容易被黑客在网络中发现数据库。改成其他端口有助于隐藏数据库,防止被黑客入侵。
• 检查方法 
  
• show global variables like 'port'; 
• 如果返回是3306,则说明需要修改端口
• 修复建议 
  
• 修改为非3306端口
2. 文件系统权限安全配置
2.1. 确保数据文件最小权限
• 建议理由 
  
• 限制数据文件的访问权限,有助于阻碍不法分子直接从数据文件中读取数据甚至读取或替换MySQL.user表中的用户和密码信息
• 检查方法 
  
• show variables where variable_name = 'datadir';
• 检查路径权限是否符合最小权限原则 
    
• ls -l /.. | egrep "^d[r|w|x]{3}------\s*.\s*mysql\s*mysql\s*\d*.*mysql"
• 如果没有返回行,则说明存在安全问题
• 修复建议 
  
• chmod 700 <'datadir'> 
• chown mysql.mysql <'datadir'> 
2.2. 确保log_bin_basename文件最小权限
• 建议理由 
  
• 限制日志文件的权限将有益于保护数据信息不泄露,或被恶意修改。
• 检查方法 
  
• show variables like 'log_bin_basename';
• 检查日志文件的权限是660属于 mysql
• 修复建议:请执行以下语句 
  
• chmod 660 <'log file'>
• chown mysql.mysql <''log file '> 
2.3. 确保log_error文件最小权限
• 建议理由 
  
• 限制日志文件的权限将有益于保护数据信息不泄露,或被恶意修改。
• 检查方法 
  
• show global variables like 'log_error';
• 检查日志文件的权限是660属于 mysql
• 修复建议:请执行以下语句 
  
• chmod 660 <'log file'>
• chown mysql.mysql <''log file'>
2.4. 确保slow_query_log文件最小权限
• 建议理由 
  
• 限制日志文件的权限将有益于保护数据信息不泄露,或被恶意修改。
• 检查方法 
  
• show variables like 'slow_query_log_file';
• 检查日志文件的权限是660属于 mysql
• 修复建议:请执行以下语句 
  
• chmod 660 <'log file'>
• chown mysql.mysql <''log file'>
2.5. 确保relay_log_basename文件最小权限
• 建议理由 
  
• 限制日志文件的权限将有益于保护数据信息不泄露,或被恶意修改。
• 检查方法 
  
• show variables like 'relay_log_basename';
• 检查日志文件的权限是660属于 mysql
• 修复建议:请执行以下语句 
  
• chmod 660 <'log file'>
• chown mysql.mysql <''log file'>
2.6. 确保general_log_file文件最小权限
• 建议理由 
  
• 限制日志文件的权限将有益于保护数据信息不泄露,或被恶意修改。
• 检查方法 
  
• show variables like 'general_log_file';
• 检查日志文件的权限是660属于 mysql
• 修复建议:请执行以下语句 
  
• chmod 660 <'log file'>
• chown mysql.mysql <''log file'>
2.7. 确保密钥文件最小权限
• 建议理由 
  
• 限制密钥文件的访问权限,防止密钥文件被盗取,被替换,被破解等情况的发生。
• 检查方法 
  
• show variables where variable_name = 'ssl_key';
• 检查路径权限是否符合最小权限原则 
    
• ls -l | egrep "^-r--------[ \t]*.[ \t]*mysql[ \t]*mysql.*$"
• 如果没有返回行,则说明存在安全问题
• 修复建议:请执行以下语句 
  
• chmod 400 <ssl_key_value>
• chown mysql.mysql < ssl_key_value >
2.8. 确保插件目录最小权限
• 建议理由 
  
• 限制插件目录的权限,防止有人恶意添加插件,这些插件会在MySQL启动时和MySQL同时启动。如果被插入恶意插件,可能会导致MySQL被控制。
• 检查方法 
  
• show variables where variable_name = 'plugin_dir';
• 检查路径权限是否符合最小权限原则 
    
• ls -l /.. | egrep "^drwxr[-w]xr[-w]x[ \t]*[0-9][ \t]*mysql[ \t]*mysql.*plugin.*$"
• 如果没有返回行,则说明存在安全问题
• 修复建议:请执行以下语句 
  
• chmod 755 < plugin_dir Value>
• chown mysql.mysql < plugin_dir Value >
2.9. 将 socket 文件放入 datadir 中,保护 socket 文件
• 建议理由 
  
• 通常 socket 目录权限默认是 644,权限较大,非属主用户也可以使用;datadir 权限为 600,权限小且严格,可以起到权限控制的效果。
• 检查方法 
  
• find <datadir> -name "mysql.sock"
• 如果没有结果
• 修改建议 
  
• socket = /datadir/mysql.sock
• 重启实例生效
3. MySQL 基本安全配置
3.1. 确保样例数据库删除
• 建议理由 
  
• 样例数据库可以被所有数据库用户访问,并且可以用来消耗系统资源删除样例库可以减少黑客攻击面。
• 检查方法 
  
• SHOW DATABASES LIKE 'test';
• 修复建议:如果存在删除样例库 
  
• DROP DATABASE "test";
3.2. 修改root用户名
• 建议理由 
  
• MySQL默认用户root应该修改名称,以减小攻击面。防止黑客针对用户名进行密码猜测攻击。
• 检查方法 
  
• 执行sql检查数据库是否有默认用户root 
    
• SELECT user from MySQL.user where user='root;
• 如果有返回行则需要修改
• 修复建议:修改用户名 
  
• update user set name='newname' where name='oldname';
• flush privileges;
3.3. 使用增强的用户密码安全策略(需要启用 SSL连接)
• 建议理由 
  
• MySQL 5.7 版本以前,默认的用户密码安全策略为 mysql_native_password,加密安全性较低,常见密码在网上可以查到字典进行反推;使用增强策略可以防止黑客对密码进行暴破。
• 检查方法 
  
• show global variables like '%default_authentication_plugin%';
• 如果结果是 mysql_native_password,需要修改
• 修改建议 
  
• set global default_authentication_plugin='sha256_password';
3.4. 确保allow-suspicious-udfs设置成false 
• 建议理由 
  
• 关闭allow-suspicious-udfs,可以防止通过共享对象文件加载存在威胁的UDFs函数。
• 检查方法 
  
• 检查配置文件确定这个参数被设置成false(没有通过命令检查的方式吗?)
• 检查MySQLd 的启动参数中 没有allow-suspicious-udfs参数
• 修复建议 
  
• 从配置文件中把allow-suspicious-udfs设置成false
• 启动参数中剔除allow-suspicious-udfs
3.5. 禁用local_infile
• 建议理由 
  
• 禁用local_infile可以阻止黑客利用sql注入来读取数据库文件,减小黑客给数据库带来的安全损失。
• 检查方法 
  
• 用sql语句检查参数状态 
    
• SHOW VARIABLES WHERE Variable_name = 'local_infile';
• 如果返回值不是off,则存在安全问题
• 修复建议:在配置文件中加入下列内容,然后重启数据库 
  
• local_infile=0
3.6. 确保skip-symbolic-links开启
• 建议理由 
  
• 开启skip-symbolic-links可以禁止数据库用户删除或重名数据文件目录之外的文件。
• 检查方法 
  
• 用sql语句检查参数状态
• SHOW variables LIKE 'have_symlink';
• 修复建议 
  
• 如果没有启动skip-symbolic-links建议把MySQL配置文件中的值设置成yes。
3.7. 确保插件daemon_memcached被禁用
• 建议理由: 
  
• 任何人可以利用daemon_memcached来访问或修改一部分数据,给数据库造成信息泄漏的隐患。
• 检查方法 
  
• SELECT * FROM information_schema.plugins WHERE PLUGIN_NAME='daemon_memcached';
• 如果有返回行数说明有插件,需要删除
• 修复建议:删除插件语句如下 
  
• uninstall plugin daemon_memcached;
3.8. 确保secure_file_priv不是空
• 建议理由 
  
• secure_file_priv限制客户端可以读取数据文件的路径。secure_file_priv设置合理的值可以有效降低sql注入后黑客读取数据库数据的可能性。
• 检查方法 
  
• SHOW GLOBAL VARIABLES WHERE Variable_name = 'secure_file_priv' AND Value<>'';
• 如果有返回内容说明安全,否则需要修复
• 修复建议:在配置文件中添加如下语句,然后重启数据库 
  
• secure_file_priv=<path_to_load_directory>>
3.9. 确保sql_mode是STRICT_ALL_TABLES模式
• 建议理由 
  
• sql_mode模式有三种,STRICT_TRANS_TABLES是其中一种模式。STRICT_TRANS_TABLES模式会检查所有更新的数据,在一定程度可以给入侵者规避检测带来阻碍。
• 检查方法 
  
• SHOW VARIABLES LIKE 'sql_mode';
• 如果有返回的是STRICT_TRANS_TABLES说明安全,否则需要修复
• 修复建议:在配置文件中添加如下语句,然后重启数据库 
  
• sql_mode=STRICT_ALL_TABLES 
3.10. 确保disconnect_on_expired_password参数是ON
• 建议理由 
  
• disconnect_on_expired_password是用来控制客户端用失效密码来访问数据库的。关闭这个参数会给数据库带来安全风险。
• 检查方法 
  
• SHOW GLOBAL VARIABLES like 'disconnect_on_expired_password';
• 如果有返回的是ON说明安全,否则需要修复
• 修复建议:在配置文件中添加如下语句,然后重启数据库 
  
• disconnect_on_expired_password =ON