参考官方文档:
https://dev.mysql.com/doc/refman/5.7/en/security.html
在考虑MySQL安装中的安全性时,您应该考虑各种可能的问题以及它们如何影响MySQL服务器和相关应用程序的安全性:
6.1.1 安全指南
在连接到互联网的计算机上使用MySQL的任何人都应阅读本节以避免最常见的安全错误。
在讨论安全性时,有必要考虑全面保护整个服务器主机(不仅仅是MySQL服务器),以抵御各种类型的攻击:窃听,修改,重放和拒绝服务。 我们并未涵盖可用性和容错的所有方面。
-- 重放攻击就是攻击者发送一个目的主机已接收过的包,来达到欺骗系统的目的,主要用于身份认证过程。即为攻击者虽然无法破解加密后的数据而获得密码,但是能仿造一个被加密后的口令数据而达到认证的目的;为了防范此类攻击,在NTLM V1/V2中加密密码的时候加入时间戳等动态可改变因素来使得加密后的密码数据无法被仿造从而达到认证的目的。
MySQL为所有连接,查询和用户可以尝试执行的其他操作使用基于访问控制列表(ACL)的安全性。 还支持MySQL客户端和服务器之间的SSL加密连接。 这里讨论的许多概念都不是特定于MySQL的; 几乎所有的应用程序都适用相同的一般思路。
运行MySQL时,请遵循以下准则:
--权限最小化原则
清单:
要防止使用彩虹表进行密码恢复,请不要在普通密码上使用这些函数。 相反,选择一些字符串作为盐,并使用哈希(哈希(密码)+盐)值。 --加盐处理
清单:
shell> telnet server_host 3306
如果telnet挂起或连接被拒绝,则端口被阻止,这是您希望的方式。 如果你得到连接和一些垃圾字符,端口是开放的,并且应该在你的防火墙或路由器上关闭,除非你有充分的理由保持它打开。
shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings
这在Linux下可用,并且应该在其他系统下进行小修改。
警告:
如果您没有看到明文数据,这并不总意味着信息实际上是加密的。 如果您需要高安全性,请咨询安全专家。
6.1.2 保持密码安全性
密码出现在MySQL的几个上下文中。 以下各节提供了使最终用户和管理员能够保证这些密码安全并避免暴露这些密码的指导原则。 另外还讨论了MySQL如何在内部使用密码哈希以及如何使用可用于实施更严格密码的插件。
6.1.2.1 最终用户密码安全指南
当您运行客户端程序以连接到MySQL服务器时,以将其公开给其他用户的方式指定您的密码是不可取的。 这里列出了您在运行客户端程序时用于指定密码的方法,以及每种方法的风险评估。 简而言之,最安全的方法是让客户端程序提示输入密码或在正确保护的选项文件中指定密码。
shell> mysql -u francis -pfrank db_name
警告:
这很方便但不安全。 在某些系统上,您的密码对系统状态程序(例如ps)可见,可由其他用户调用以显示命令行。 MySQL客户端通常在其初始化序列中用零覆盖命令行密码参数。 但是,仍然有一个短暂的时间间隔,可以看到该值。 另外,在某些系统上,这种覆盖策略是无效的,密码对ps仍然可见。 (SystemV Unix系统和其他可能会遇到这个问题。)
如果您的操作环境设置为在终端窗口的标题栏中显示当前命令,则只要该命令正在运行,密码仍然可见,即使该命令在窗口内容区域中滚动出视图也是如此。
shell> mysql -u francis -p db_name
Enter password: ********
*字符表示您输入密码的位置。 输入密码时不显示密码。
以这种方式输入密码比在命令行中指定密码更安全,因为其他用户不可见。 但是,这种输入密码的方法仅适用于交互式运行的程序。 如果您想从非交互式脚本中调用客户端,则无法通过键盘输入密码。 在某些系统上,您甚至可能会发现脚本的第一行被读取并解释(错误地)为您的密码。
[client]
password=your_pass
为确保密码安全,除了您自己以外,任何人都无法访问该文件。 为确保这一点,请将文件访问模式设置为400或600.例如:
shell> chmod 600 .my.cnf
要从命令行命名包含密码的特定选项文件,请使用--defaults-file = file_name选项,其中file_name是该文件的完整路径名。 例如:
shell> mysql --defaults-file=/home/francis/mysql-opts
这种指定你的MySQL密码的方法必须被认为是非常不安全的,不应该被使用。 某些版本的ps包含显示正在运行的进程环境的选项。 在某些系统上,如果您设置了MYSQL_PWD,则您的密码将暴露给运行ps的任何其他用户。 即使在没有这种ps版本的系统上,假设没有其他用户可以检查过程环境的方法也是不明智的。
在Unix上,mysql客户端将执行语句的记录写入历史文件(参见第4.5.1.3节“mysql日志记录”)。 默认情况下,该文件名为.mysql_history,并且在您的主目录中创建。 密码可以在SQL语句(如CREATE USER和ALTER USER)中以纯文本形式写入,因此如果使用这些语句,它们将记录在历史文件中。 为了保持这个文件的安全,使用限制性访问模式,就像之前对.my.cnf文件所描述的一样。
如果您的命令解释程序配置为保留历史记录,则保存命令的任何文件都将包含在命令行中输入的MySQL密码。 例如,bash使用〜/ .bash_history。 任何这样的文件都应该有一个限制性的访问模式。
6.1.2.2 管理员的密码安全指南
数据库管理员应该使用以下准则来确保密码的安全。
MySQL将用户帐户的密码存储在mysql.user表中。 永远不应该授予给任何非管理账户。
帐户密码可以过期,以便用户必须重置它们。
validate_password插件可用于对可接受的密码实施策略。
有权修改插件目录(plugin_dir系统变量的值)或指定插件目录位置的my.cnf文件的用户可以替换插件并修改插件提供的功能,包括身份验证插件。
诸如可能写入密码的日志文件等文件应该受到保护。
6.1.2.3 密码和登录
可以在SQL语句(如CREATE USER,GRANT,SET PASSWORD和调用PASSWORD()函数的语句)中将密码写为纯文本。 如果MySQL服务器记录了这样的语句,那么访问日志的任何人都可以看到它们的密码。
以下语句可以避免以明文形式编写密码:
CREATE USER ... IDENTIFIED BY ...
ALTER USER ... IDENTIFIED BY ...
GRANT ... IDENTIFIED BY ...
SET PASSWORD ...
SLAVE START ... PASSWORD = ...
CREATE SERVER ... OPTIONS(... PASSWORD ...)
ALTER SERVER ... OPTIONS(... PASSWORD ...)
这些语句中的密码被重写,不会写入常规查询日志,慢速查询日志和二进制日志的语句文本中。 重写不适用于其他语句。 特别是,引用文字密码的mysql.user表的INSERT或UPDATE语句按原样记录,因此您应该避免使用这些语句。 (无论如何,不鼓励直接修改授权表。)
--直接update mysql.user表不会被加密
对于通用查询日志,可以通过使用--log-raw选项启动服务器来禁止密码重写。 出于安全原因,不建议将此选项用于生产用途。 出于诊断目的,查看服务器收到的语句的确切文本可能很有用。
审计日志插件生成的审计日志文件的内容未加密。 出于安全原因,这个文件应该写入一个只能由MySQL服务器访问的目录以及具有合法理由查看日志的用户。
如果安装了查询重写插件,则服务器收到的语句可能会被重写(请参阅查询重写插件)。 在这种情况下,--log-raw选项会影响语句记录,如下所示:
--密码重写机制
密码重写仅在需要纯文本密码时才会发生。 对于需要密码哈希值的语法,不会发生重写。 如果为这种语法错误地提供明文密码,则密码将按给定的方式记录,而不会重写。 例如,下面的语句会按照所示进行记录,因为需要密码哈希值:
CREATE USER 'user1'@'localhost' IDENTIFIED BY PASSWORD 'not-so-secret';
要防范日志文件遭受无端暴露,请将它们放入限制访问服务器和数据库管理员的目录中。 如果服务器记录到mysql数据库中的表中,只将这些表的访问权授予数据库管理员。
复制从服务器将复制主服务器的密码存储在主资料库中,该资料库 可以是文件或表(请参见第16.2.4节“复制中继和状态日志”)。 确保只能由数据库管理员访问资料库 。 将密码存储在文件中的替代方法是使用START SLAVE语句指定用于连接到主服务器的凭据。
使用受限制的访问模式来保护包含日志表或包含密码的日志文件的数据库备份。
6.1.2.4 在MYSQL 中的密码hash
注意:
本节中的信息仅在MySQL 5.7.5之前完全适用,并且仅适用于使用mysql_native_password或mysql_old_password身份验证插件的帐户。 在MySQL 5.7.5中删除了对4.1之前的密码哈希的支持。 这包括删除mysql_old_password身份验证插件和OLD_PASSWORD()函数。 此外,secure_auth不能被禁用,并且old_passwords不能被设置为1。
从MySQL 5.7.5开始,只有有关4.1密码哈希和mysql_native_password验证插件的信息才是相关的。
MySQL在mysql数据库的user表中列出用户帐户。 虽然user表不存储密码的明文版本,但是可以从中计算出一个散列值,为每个MySQL帐户分配一个密码。
MySQL在客户端/服务器通信的两个阶段使用密码:
换句话说,当客户端首次尝试连接时,服务器在验证过程中检查散列值。 如果连接的客户端调用PASSWORD()函数或使用密码生成语句来设置或更改密码,则服务器会生成哈希值。
MySQL中的密码哈希方法具有以下描述的历史记录。 这些更改通过计算密码哈希值的PASSWORD()函数以及存储密码的用户表结构中的更改来说明。
原始(4.1之前的)哈希方法
原始的哈希方法产生了一个16字节的字符串。 这样的哈希看起来像这样:
mysql> SELECT PASSWORD('mypass');
+--------------------+
| PASSWORD('mypass') |
+--------------------+
| 6f8c114b58f2ce9e |
+--------------------+
要存储帐户密码,用户表的密码列在这一点上是16个字节长。
4.1 Hashing 方法
MySQL 4.1的变化发生在两个阶段:
mysql> SELECT PASSWORD('mypass'); +-------------------------------------------+
| PASSWORD('mypass') |
+-------------------------------------------+ | *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 | +-------------------------------------------+
较长的密码哈希格式具有更好的加密属性,基于较长哈希的客户端身份验证比基于较旧短哈希的客户端身份验证更安全。
为了适应更长的密码散列,用户表中的密码列在此处已被更改为41字节,即当前长度。
扩展的密码列可以存储4.1以前版本和4.1版本的密码哈希值。 任何给定散列值的格式可以通过两种方式确定:
为了允许明确生成4.1以前的密码哈希,我们做了两项额外的修改:
为了允许DBA控制客户端被允许连接的方式,添加了secure_auth系统变量。 在禁用或启用此变量的情况下, 启动服务器允许或禁止客户端使用旧的4.1之前的密码散列方法进行连接。 在MySQL 5.6.5之前,secure_auth默认是禁用的。 从5.6.5开始,默认情况下启用secure_auth以提升更安全的默认配置DBA可以自行决定禁用它,但不建议这样做,并且4.1之前的密码哈希值已弃用,应予以避免。
另外,mysql客户端支持类似于secure_auth的--secure-auth选项,但支持来自客户端的选项。 它可以用来阻止使用4.1之前的密码散列的较不安全帐户的连接。 此选项在MySQL 5.6.7之前默认为禁用,此后启用。
与散列方法相关的兼容性问题
以下情况在MySQL 4.1或更高版本中是可能的。 这些因素是密码列是短还是长的,以及如果长的,服务器是否启用了启用或禁用old_passwords。
场景1:用户表中的短密码列:
当4.1版之前的MySQL安装已升级到4.1或更高版本,但尚未运行mysql_upgrade以升级mysql数据库中的系统表时,会出现此情况。 (这不是推荐的配置,因为它不允许使用更安全的4.1密码散列。)
场景2:长密码列; 服务器以old_passwords = 1启动:
在这种情况下,新创建的帐户具有短密码哈希值,因为old_passwords = 1可防止生成长哈希值。 另外,如果您在将old_passwords设置为1之前创建了一个具有长散列的帐户,那么在old_passwords = 1时更改帐户密码会导致帐户被设置一个简短密码,导致它失去了较长散列的安全优势。
要创建一个长密码散列的新帐户,或者要将任何现有帐户的密码更改为使用长散列,请首先将old_passwords的会话值设置为0,同时将全局值设置为1,如前所述。
在这种情况下,服务器具有最新的密码列,但正在使用默认密码哈希方法集来运行以生成4.1之前的哈希值。 这不是推荐的配置,但在4.1之前的客户端和密码升级到4.1或更高版本的过渡时期可能会有用。 完成后,最好使用old_passwords = 0和secure_auth = 1运行服务器。
6.1.3 使MySQL免受攻击者的攻击
当你连接到MySQL服务器时,你应该使用密码。 密码不通过连接以明文形式传输。 客户端连接序列中的密码处理在MySQL 4.1.1中升级,非常安全。 如果您仍在使用4.1.1之前版本的密码,则加密算法不如新算法那么强大。 通过一些努力,一个能够嗅探客户端和服务器之间流量的聪明的攻击者可以破解密码。
所有其他信息以文本形式传输,任何能够观看连接的人都可以阅读。 如果客户端和服务器之间的连接经过不可信网络,并且您担心这一点,则可以使用压缩协议来使流量难以解密。 您还可以使用MySQL的内部SSL支持来使连接更安全。 请参见第6.4节“使用加密连接”。 或者,使用SSH获取MySQL服务器和MySQL客户端之间的加密TCP / IP连接。 您可以在http://www.openssh.org/上找到开源SSH客户端,以及http://en.wikipedia.org/wiki/Comparison_of_SSH_clients上的开源SSH客户端和商用SSH客户端的比较。
要使MySQL系统安全,您应该强烈考虑以下建议:
mysqld可以(而且应该)作为普通的非特权用户来运行。 您可以创建一个名为mysql的单独Unix帐户,以使所有事情更加安全。 只能用这个帐号来管理MySQL。 要以不同的Unix用户身份启动mysqld,请添加一个用户选项,用于在指定服务器选项的my.cnf选项文件的[mysqld]组中指定用户名。 例如:
[mysqld]
user=mysql
这会导致服务器以指定用户身份启动,无论您是手动启动还是使用mysqld_safe或mysql.server。
以root用户身份运行mysqld并不意味着您需要更改用户表中的root用户名。 MySQL帐户的用户名与Unix帐户的用户名无关。
FILE权限也可以用来读取任何世界可读的或服务器运行的Unix用户可以访问的文件。 有了这个特权,你可以读取任何文件到数据库表中。 这可能会被滥用,例如,使用LOAD DATA将/etc/passwd加载到表中,然后可以使用SELECT进行显示。
要限制可以读取和写入文件的位置,请将secure_file_priv系统设置为特定的目录。
mysqld为拥有SUPER权限的用户保留一个额外的连接,以便MySQL root用户可以登录并检查服务器活动,即使所有正常连接都在使用中。
SUPER特权可用于终止客户端连接,通过更改系统变量的值来更改服务器操作,并控制复制服务器。
6.1.4 安全性相关的mysqld选项和变量
显示影响安全性的mysqld选项和系统变量
可以参考:
https://dev.mysql.com/doc/refman/5.7/en/security-options.html
6.1.5 如何以普通用户身份运行MySQL
在Windows上,您可以使用普通用户帐户作为Windows服务运行服务器。
在Linux上,对于使用MySQL存储库,RPM软件包或Debian软件包执行的安装,MySQL服务器mysqld应该由本地mysql操作系统用户启动。 作为安装的一部分包含的init脚本不支持由另一个操作系统用户启动。
在Unix上(或者用于使用tar或tar.gz软件包进行安装的Linux),MySQL服务器mysqld可以由任何用户启动并运行。 但是,出于安全原因,您应该避免以Unix root用户身份运行服务器。 要将mysqld更改为普通非特权Unix用户user_name,必须执行以下操作:
shell> chown -R user_name /path/to/mysql/datadir
如果您不这样做,则服务器在以user_name身份运行时将无法访问数据库或表。
如果MySQL数据目录中的目录或文件是符号链接,chown -R可能不会遵循符号链接。 如果没有,您还需要关注这些链接并更改它们指向的目录和文件。
[mysqld]
user=user_name
如果你的Unix机器本身没有安全保护,你应该把密码分配给授权表中的MySQL root帐户。 否则,任何在该机器上拥有登录帐户的用户都可以使用--use=root选项运行mysql客户端并执行任何操作。 (在任何情况下,都要给MySQL帐户分配密码,当服务器主机上存在其他登录帐户时尤其如此。)
6.1.6 LOAD DATA LOCAL的安全问题
LOAD DATA语句可以加载位于服务器主机上的文件,或者,如果指定了LOCAL关键字,则可以加载客户端主机上的文件。
LOAD DATA的LOCAL版本存在两个潜在的安全问题:
为避免LOAD DATA问题,客户应避免使用LOCAL。 为避免连接到不受信任的服务器,客户端可以建立安全连接,并通过使用--ssl-mode = VERIFY_IDENTITY选项和相应的CA证书进行连接来验证服务器身份。
要使管理员和应用程序能够管理本地数据加载功能,LOCAL配置的工作方式如下所示:
默认情况下,MySQL二进制发行版中的客户端库是在启用 ENABLED_LOCAL_INFILE的情况下编译的。 如果您从源代 码编译MySQL,请根据无显式参数的客户端是否分别禁用或启用LOCAL功能,将其配置为禁用或启用ENABLED_LOCAL_INFILE。
[client]
loose-local-infile=0
或:
[client]
loose-local-infile=1
如果禁用LOCAL功能,则在服务器或客户端上,尝试发出LOAD DATA LOCAL语句的客户端会收到以下错误消息:
ERROR 1148: The used command is not allowed with this MySQL version
6.1.7 客户端编程安全指南
访问MySQL的应用程序不应该信任用户输入的任何数据,他们可以尝试通过在Web form,URL或您已构建的任何应用程序中输入特殊或转义字符序列来欺骗您的代码。 如果用户输入类似的东西,请确保您的应用程序保持安全; DROP DATABASE mysql ;. 这是一个极端的例子,但是如果你没有为它们做准备,那么由于黑客使用类似的技术可能会导致大量的安全漏洞和数据丢失。
一个常见的错误是仅保护字符串数据值。 请记得检查数字数据。 如果应用程序在用户输入值234时生成查询(如SELECT * FROM table WHERE ID = 234),则用户可以输入值234或1 = 1以使应用程序生成查询SELECT * FROM table WHERE ID = 234或1 = 1。 结果,服务器检索表中的每一行。 这会暴露每一行并导致过多的服务器负载。 防止此类攻击的最简单方法是在数字常量周围使用单引号:SELECT * FROM table WHERE ID ='234'。 如果用户输入额外信息,则全部成为字符串的一部分。 在数字上下文中,MySQL会自动将此字符串转换为数字,并从中删除任何尾随的非数字字符。
--一般是在输入端要做输入的正则匹配,不匹配的直接返回非法输入。
有时候人们会认为如果一个数据库只包含公开可用的数据,它就不需要保护。 这是不正确的。 即使允许在数据库中显示任何行,也应该防止拒绝服务攻击(例如,基于前一段中导致服务器浪费资源的技术的攻击)。 否则,您的服务器将无法响应合法用户。
检查列表:
许多应用程序编程接口提供了转义数据值中特殊字符的方法。 正确使用,这可以防止应用程序用户输入值导致应用程度产生不是你期望的其他语句:
如果必须使用较旧的ext/mysql扩展,那么为了转义,使用mysql_real_escape_string_quote()函数而不是mysql_escape_string()或addslashes(),因为只有mysql_real_escape_string_quote()是可识别字符集的; 当使用(无效)多字节字符集时,其他函数可以被“绕过”。
其他编程接口可能具有相似的功能。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69946831/viewspace-3119479/ ,如需转载,请注明出处,否则将追究法律责任。