ITPub博客

首页 > 数据库 > > 6.1 安全概述

6.1 安全概述

作者:飘絮絮絮丶 时间:2020-05-14 13:27:24 0 删除 编辑

参考官方文档:

dev.mysql.com/doc/refma





在考虑MySQL安装中的安全性时,您应该考虑各种可能的问题以及它们如何影响MySQL服务器和相关应用程序的安全性:



  • 影响安全性的一般因素。 这些包括选择良好的密码,不授予用户不必要的特权,通过防止SQL注入和数据损坏等来确保应用程序的安全性。
  • 安装本身的安全性。 数据文件,日志文件和安装的所有应用程序文件应受到保护,以确保它们不可被未授权方读取或写入。(系统级别权限)
  • 数据库系统本身的访问控制和安全性,包括授予访问数据库的用户和数据库,视图和数据库中正在使用的存储过程。
  • 安全相关插件提供的功能


  • MySQL和你的系统的网络安全。 安全性与个人用户的授权相关,但您也可能希望限制MySQL,使其仅在MySQL服务器主机上本地可用,或仅限于其他有限的其他主机。
  • 确保您有足够和适当的数据库文件,配置和日志文件的备份 。 另外,请确保您有适当的恢复解决方案,并测试您是否能够成功从备份中恢复。










6.1.1 安全指南



在连接到互联网的计算机上使用MySQL的任何人都应阅读本节以避免最常见的安全错误。







在讨论安全性时,有必要考虑全面保护整个服务器主机(不仅仅是MySQL服务器),以抵御各种类型的攻击:窃听,修改,重放和拒绝服务。 我们并未涵盖可用性和容错的所有方面。





-- 重放攻击就是攻击者发送一个目的主机已接收过的包,来达到欺骗系统的目的,主要用于身份认证过程。即为攻击者虽然无法破解加密后的数据而获得密码,但是能仿造一个被加密后的口令数据而达到认证的目的;为了防范此类攻击,在NTLM V1/V2中加密密码的时候加入时间戳等动态可改变因素来使得加密后的密码数据无法被仿造从而达到认证的目的。



MySQL为所有连接,查询和用户可以尝试执行的其他操作使用基于访问控制列表(ACL)的安全性。 还支持MySQL客户端和服务器之间的SSL加密连接。 这里讨论的许多概念都不是特定于MySQL的; 几乎所有的应用程序都适用相同的一般思路。



运行MySQL时,请遵循以下准则:

  • 永远不要给任何人(MySQL根帐户除外)访问mysql数据库中的用户表! 这很关键。




  • 了解MySQL访问权限系统的工作方式(请参见第6.2节“MySQL访问权限系统”)。 使用GRANT和REVOKE语句来控制对MySQL的访问。 不要给予超出必要的权限。 切勿将权限授予所有主机。

--权限最小化原则

清单:


  • 试试mysql -u root。 如果您能够成功连接到服务器而不需要密码,任何人都可以以具有完全权限的MySQL root用户身份连接到MySQL服务器! 查看MySQL安装说明,特别注意关于设置root密码的信息。
  • 使用SHOW GRANTS语句来检查哪些帐户有权访问什么。 然后使用REVOKE语句删除那些不必要的权限。




  • 不要在数据库中存储明文密码。 如果您的计算机受到威胁,入侵者可以获取完整的密码列表并使用它们。 相反,使用SHA2()或其他单向哈希函数并存储哈希值。




要防止使用彩虹表进行密码恢复,请不要在普通密码上使用这些函数。 相反,选择一些字符串作为盐,并使用哈希(哈希(密码)+盐)值。 --加盐处理





  • 不要从字典中选择密码。 存在破解密码的特殊程序。 即使像“xfish98”这样的密码也很糟糕。 更好的是“duag98”,其中包含相同的单词“鱼”,但在标准的QWERTY键盘上键入左侧的一个键。 另一种方法是使用从句子中每个单词的第一个字符中获取的密码(例如,“Four score and seven years ago”导致密码为“Fsasya”)。 密码很容易记住和键入,但对于不知道该句子的人很难猜出。 在这种情况下,您可以另外用数字替换数字来获得短语“4分和7年前”,产生更难猜测的密码“4sa7ya”。




  • 投资防火墙。 这可以保护您免受任何软件中至少50%的所有类型的漏洞攻击。 将MySQL放在防火墙后面或 demilitarized 区(DMZ)。

清单:

  • 尝试使用nmap等工具从Internet扫描端口。 MySQL默认使用端口3306。 不应该从不受信任的主机访问此端口。 作为检查MySQL端口是否打开的简单方法,请尝试从某个远程计算机执行以下命令,其中server_host是运行MySQL服务器的主机的主机名或IP地址:


shell> telnet server_host 3306

如果telnet挂起或连接被拒绝,则端口被阻止,这是您希望的方式。 如果你得到连接和一些垃圾字符,端口是开放的,并且应该在你的防火墙或路由器上关闭,除非你有充分的理由保持它打开。




  • 访问MySQL的应用程序不应该信任用户输入的任何数据,应该使用适当的防御性编程技术来编写。(防SQL注入)
  • 不要通过Internet传输简单(未加密)的数据。 每个有时间和能力的人都可以访问这些信息,并将其用于自己的目的。 相反,请使用SSL或SSH等加密协议。 MySQL支持内部SSL连接。 另一种技术是使用SSH端口转发为通信创建加密(和压缩)隧道。
  • 学习使用tcpdump和 strings 工具。 在大多数情况下,您可以通过发出如下命令来检查MySQL数据流是否未加密:


shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings



这在Linux下可用,并且应该在其他系统下进行小修改。





警告:

如果您没有看到明文数据,这并不总意味着信息实际上是加密的。 如果您需要高安全性,请咨询安全专家。







6.1.2 保持密码安全性



密码出现在MySQL的几个上下文中。 以下各节提供了使最终用户和管理员能够保证这些密码安全并避免暴露这些密码的指导原则。 另外还讨论了MySQL如何在内部使用密码哈希以及如何使用可用于实施更严格密码的插件。





6.1.2.1 最终用户密码安全指南

当您运行客户端程序以连接到MySQL服务器时,以将其公开给其他用户的方式指定您的密码是不可取的。 这里列出了您在运行客户端程序时用于指定密码的方法,以及每种方法的风险评估。 简而言之,最安全的方法是让客户端程序提示输入密码或在正确保护的选项文件中指定密码。



  • 使用mysql_config_editor实用程序,该实用程序使您能够将认证凭证存储在名为.mylogin.cnf的加密登录路径文件中。 MySQL客户端程序可以稍后阅读该文件,以获取用于连接到MySQL服务器的认证凭证。
  • 在命令行上使用-pyour_pass或--password=your_pass选项。 例如:




shell> mysql -u francis -pfrank db_name



警告:

这很方便但不安全。 在某些系统上,您的密码对系统状态程序(例如ps)可见,可由其他用户调用以显示命令行。 MySQL客户端通常在其初始化序列中用零覆盖命令行密码参数。 但是,仍然有一个短暂的时间间隔,可以看到该值。 另外,在某些系统上,这种覆盖策略是无效的,密码对ps仍然可见。 (SystemV Unix系统和其他可能会遇到这个问题。)





如果您的操作环境设置为在终端窗口的标题栏中显示当前命令,则只要该命令正在运行,密码仍然可见,即使该命令在窗口内容区域中滚动出视图也是如此。





  • 在命令行上使用-p或--password选项,不指定密码值。 在这种情况下,客户端程序交互式地请求密码:


shell> mysql -u francis -p db_name

Enter password: ********



*字符表示您输入密码的位置。 输入密码时不显示密码。

以这种方式输入密码比在命令行中指定密码更安全,因为其他用户不可见。 但是,这种输入密码的方法仅适用于交互式运行的程序。 如果您想从非交互式脚本中调用客户端,则无法通过键盘输入密码。 在某些系统上,您甚至可能会发现脚本的第一行被读取并解释(错误地)为您的密码。



  • 将您的密码存储在选项文件中。 例如,在Unix上,您可以在主目录中的.my.cnf文件的[client]部分列出您的密码:


[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_PWD环境变量中。


这种指定你的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选项会影响语句记录,如下所示:

  • 如果没有--log-raw,服务器将记录查询重写插件返回的语句。 这可能与收到的语句有所不同。
  • 使用--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()函数来生成密码哈希,或者使用密码生成语句(CREATE USER,GRANT或SET PASSWORD)来完成此操作。






换句话说,当客户端首次尝试连接时,服务器在验证过程中检查散列值。 如果连接的客户端调用PASSWORD()函数或使用密码生成语句来设置或更改密码,则服务器会生成哈希值。



MySQL中的密码哈希方法具有以下描述的历史记录。 这些更改通过计算密码哈希值的PASSWORD()函数以及存储密码的用户表结构中的更改来说明。



原始(4.1之前的)哈希方法



原始的哈希方法产生了一个16字节的字符串。 这样的哈希看起来像这样:

mysql> SELECT PASSWORD('mypass');

+--------------------+

| PASSWORD('mypass') |

+--------------------+

| 6f8c114b58f2ce9e |

+--------------------+

要存储帐户密码,用户表的密码列在这一点上是16个字节长。





4.1 Hashing 方法

MySQL 4.1引入了密码哈希,提供了更好的安全性并降低了密码被截取的风险。 这种变化有几个方面:

  • 由PASSWORD()函数生成的不同格式的密码值
  • 扩大 Password 栏
  • 控制默认的哈希方法
  • 控制尝试连接到服务器的客户端所允许的哈希方法




MySQL 4.1的变化发生在两个阶段:

  • MySQL 4.1.0使用了4.1哈希方法的初步版本。 这种方法很短暂,下面的讨论没有提到更多关于它的内容。
  • 在MySQL 4.1.1中,哈希方法被修改以产生更长的41字节哈希值:


mysql> SELECT PASSWORD('mypass'); +-------------------------------------------+

| PASSWORD('mypass') |

+-------------------------------------------+ | *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 | +-------------------------------------------+



较长的密码哈希格式具有更好的加密属性,基于较长哈希的客户端身份验证比基于较旧短哈希的客户端身份验证更安全。





为了适应更长的密码散列,用户表中的密码列在此处已被更改为41字节,即当前长度。



扩展的密码列可以存储4.1以前版本和4.1版本的密码哈希值。 任何给定散列值的格式可以通过两种方式确定:

  • 长度:4.1和4.1之前的哈希分别是41和16个字节。
  • 4.1格式的密码哈希总是以*字符开头,而4.1之前的格式的密码永远不会。






为了允许明确生成4.1以前的密码哈希,我们做了两项额外的修改:



  • 添加了OLD_PASSWORD()函数,该函数以16字节格式返回散列值。
  • 为了兼容性,添加了old_passwords系统变量,以使DBA和应用程序能够控制散列方法。 默认的old_passwords值为0会导致散列使用4.1方法(41字节散列值),但设置old_passwords=1会导致散列使用4.1之前的方法。 在这种情况下,PASSWORD()产生16个字节的值,相当于OLD_PASSWORD()






为了允许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:用户表中的短密码列:

  • 只有短的哈希值可以存储在密码列中。
  • 服务器在客户端身份验证期间仅使用较短的哈希。
  • 对于连接的客户端,涉及PASSWORD()函数或密码生成语句的密码哈希生成操作仅使用短哈希。 对帐户密码的任何更改都会导致该帐户拥有较短的密码哈希值。
  • old_passwords的值是不相关的,因为使用简短密码列,服务器无论如何都只生成简短密码散列。




当4.1版之前的MySQL安装已升级到4.1或更高版本,但尚未运行mysql_upgrade以升级mysql数据库中的系统表时,会出现此情况。 (这不是推荐的配置,因为它不允许使用更安全的4.1密码散列。)



场景2:长密码列; 服务器以old_passwords = 1启动:

  • 短密码或长密码可以存储在密码栏中。
  • 4.1和更高版本的客户端可以对具有短或长哈希的帐户进行身份验证。
  • 4.1之前的客户端只能对具有较短哈希值的帐户进行身份验证。
  • 对于连接的客户端,涉及PASSWORD()函数或密码生成语句的密码哈希生成操作仅使用短哈希。 对帐户密码的任何更改都会导致该帐户拥有较短的密码哈希值。




在这种情况下,新创建的帐户具有短密码哈希值,因为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连接。 您可以在openssh.org/上找到开源SSH客户端,以及en.wikipedia.org/wiki/C上的开源SSH客户端和商用SSH客户端的比较。







要使MySQL系统安全,您应该强烈考虑以下建议:

  • 要求所有MySQL帐户都有密码。 客户程序不一定知道运行它的人的身份。 客户端/服务器应用程序的常见情况是,用户可以指定客户端程序的任何用户名。 例如,如果other_user没有密码的话 ,任何人都可以像其他人那样使用mysql程序进行连接,只需将其作为mysql -u other_user db_name调用即可。 如果所有帐户都有密码,则使用其他用户的帐户连接变得更加困难。
  • 确保对于运行mysqld的用户是唯一有权限读写数据库目录的unix用户。
  • 切勿以Unix root用户身份运行MySQL服务器。 这是非常危险的,因为任何具有FILE特权的用户都可以使服务器以root身份创建文件(例如〜root/.bashrc)。 为了防止这种情况发生,mysqld拒绝以root身份运行,除非使用--user = root选项明确指定。




mysqld可以(而且应该)作为普通的非特权用户来运行。 您可以创建一个名为mysql的单独Unix帐户,以使所有事情更加安全。 只能用这个帐号来管理MySQL。 要以不同的Unix用户身份启动mysqld,请添加一个用户选项,用于在指定服务器选项的my.cnf选项文件的[mysqld]组中指定用户名。 例如:



[mysqld]

user=mysql





这会导致服务器以指定用户身份启动,无论您是手动启动还是使用mysqld_safe或mysql.server。



以root用户身份运行mysqld并不意味着您需要更改用户表中的root用户名。 MySQL帐户的用户名与Unix帐户的用户名无关。



  • 不要将FILE权限授予非管理员用户。 任何具有此特权的用户都可以使用mysqld守护进程的权限在文件系统中的任何位置写入文件。 这包括服务器的数据目录,其中包含实现特权表的文件。 要使FILE权限操作更安全一些,使用SELECT ... INTO OUTFILE生成的文件不会覆盖现有文件,并且每个人都可以写入。


FILE权限也可以用来读取任何世界可读的或服务器运行的Unix用户可以访问的文件。 有了这个特权,你可以读取任何文件到数据库表中。 这可能会被滥用,例如,使用LOAD DATA将/etc/passwd加载到表中,然后可以使用SELECT进行显示。



要限制可以读取和写入文件的位置,请将secure_file_priv系统设置为特定的目录。



  • 不要授予非管理员用户的PROCESS或SUPER权限。 mysqladmin processlist和SHOW PROCESSLIST的输出显示了当前正在执行的任何语句的文本,因此任何被允许查看服务器进程列表的用户都可以看到其他用户发出的语句,例如UPDATE用户SET password = PASSWORD('not_secure')。



mysqld为拥有SUPER权限的用户保留一个额外的连接,以便MySQL root用户可以登录并检查服务器活动,即使所有正常连接都在使用中。


SUPER特权可用于终止客户端连接,通过更改系统变量的值来更改服务器操作,并控制复制服务器。





  • 不允许使用符号链接表。 (使用--skip-symbolic-links选项可以禁用此功能。)如果以root身份运行mysqld,这一点尤其重要,因为任何拥有对服务器数据目录的写入访问权限的人都可以删除系统中的任何文件! 请参见第8.12.3.2节“在Unix上使用MyISAM表的符号链接”。




  • 在第23.6节“存储程序和视图的访问控制”中讨论的编写存储程序和视图的安全准则 。
  • 如果你不信任你的DNS,你应该在授权表中使用IP地址而不是主机名。 无论如何,您应该非常小心使用包含通配符的主机名值创建授权表条目。
  • 如果您想限制允许单个帐户的连接数量,可以通过在mysqld中设置max_user_connections变量来实现。 CREATE USER和ALTER USER语句还支持资源控制选项,用于限制授予帐户的服务器使用范围。
  • 如果插件目录可由服务器写入,则用户可以使用SELECT ... INTO DUMPFILE将可执行代码写入目录中的文件。 这可以通过将plugin_dir只读给服务器或通过将--secure-file-priv设置为 SELECT 写入的目录来防止。






6.1.4 安全性相关的mysqld选项和变量





显示影响安全性的mysqld选项和系统变量

可以参考:



dev.mysql.com/doc/refma









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,必须执行以下操作:



  • 停止服务器(如果它正在运行)(使用mysqladmin shutdown)。
  • 更改数据库目录和文件,以便user_name具有读写文件的权限(您可能需要以Unix root用户身份执行此操作):


shell> chown -R user_name /path/to/mysql/datadir



如果您不这样做,则服务器在以user_name身份运行时将无法访问数据库或表。



如果MySQL数据目录中的目录或文件是符号链接,chown -R可能不会遵循符号链接。 如果没有,您还需要关注这些链接并更改它们指向的目录和文件。

  • 以用户user_name的身份启动服务器。 另一种方法是以Unix root用户身份启动mysqld并使用--user = user_name选项。 启动mysqld,然后在接受任何连接之前切换为以Unix用户user_name身份运行。
  • 要在系统启动时自动以给定用户身份启动服务器,请通过向/etc/my.cnf选项文件的[mysqld]组或服务器数据中的my.cnf选项文件添加用户选项来指定用户名 目录。 例如:




[mysqld]

user=user_name



如果你的Unix机器本身没有安全保护,你应该把密码分配给授权表中的MySQL root帐户。 否则,任何在该机器上拥有登录帐户的用户都可以使用--use=root选项运行mysql客户端并执行任何操作。 (在任何情况下,都要给MySQL帐户分配密码,当服务器主机上存在其他登录帐户时尤其如此。)







6.1.6 LOAD DATA LOCAL的安全问题





LOAD DATA语句可以加载位于服务器主机上的文件,或者,如果指定了LOCAL关键字,则可以加载客户端主机上的文件。



LOAD DATA的LOCAL版本存在两个潜在的安全问题:



  • 从客户端主机到服务器主机的文件传输是由MySQL服务器启动的。 理论上,可以构建一个修补服务器,告诉客户端程序在LOAD DATA语句中传输服务器选择的文件,而不是客户端命名的文件。 这样的服务器可以访问客户端主机上的任何客户端用户可读取访问的文件。 (补丁服务器实际上可以向任何语句回复文件传输请求,而不仅仅是LOAD DATA LOCAL,所以更重要的问题是客户端不应连接到不受信任的服务器。)
  • 在客户端从Web服务器连接的Web环境中,用户可以使用LOAD DATA LOCAL读取Web服务器进程读取访问的任何文件(假设用户可以针对SQL Server运行任何语句)。 在这种环境下,与MySQL服务器相关的客户端实际上是Web服务器,而不是由连接到Web服务器的用户运行的远程程序。






为避免LOAD DATA问题,客户应避免使用LOCAL。 为避免连接到不受信任的服务器,客户端可以建立安全连接,并通过使用--ssl-mode = VERIFY_IDENTITY选项和相应的CA证书进行连接来验证服务器身份。





要使管理员和应用程序能够管理本地数据加载功能,LOCAL配置的工作方式如下所示:



  • 在服务器端:
    • local_infile系统变量控制服务器端LOCAL功能。 根据local_infile设置,服务器拒绝或允许客户端上已启用LOCAL的客户端加载本地数据。 默认情况下,启用local_infile。
    • 要显式地导致服务器拒绝或允许LOAD DATA LOCAL语句(无论在构建时或运行时如何配置客户端程序和库),用local_infile禁用或启用来启动mysqld 。 local_infile也可以在运行时设置。




  • 在客户端:
    • ENABLED_LOCAL_INFILE CMake选项控制MySQL客户端库的已编译默认LOCAL功能。 因此,没有明确参数的客户端根据MySQL构建时指定的ENABLED_LOCAL_INFILE设置禁用或启用LOCAL功能。


默认情况下,MySQL二进制发行版中的客户端库是在启用 ENABLED_LOCAL_INFILE的情况下编译的。 如果您从源代 码编译MySQL,请根据无显式参数的客户端是否分别禁用或启用LOCAL功能,将其配置为禁用或启用ENABLED_LOCAL_INFILE。





  • 使用C API的客户端程序可通过调用mysql_options()来禁用或启用MYSQL_OPT_LOCAL_INFILE选项来显式控制加载数据加载。
  • 对于mysql客户端,默认禁用本地数据加载。 要明确禁用或启用它,请使用--local-infile = 0或--local-infile [= 1]选项。
  • 对于mysqlimport客户端,默认禁用本地数据加载。 要明确禁用或启用它,请使用--local = 0或--local [= 1]选项。
  • 如果在Perl脚本或从选项文件读取[client]组的其他程序中使用LOAD DATA LOCAL,则可以向该组增加local-infile选项设置。 为防止不理解此选项的程序出现问题,请使用loose-前缀指定它:


[client]

loose-local-infile=0

或:

[client]

loose-local-infile=1

  • 在所有情况下,客户端成功使用LOCAL加载操作也要求服务器允许它。




如果禁用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会自动将此字符串转换为数字,并从中删除任何尾随的非数字字符。



--一般是在输入端要做输入的正则匹配,不匹配的直接返回非法输入。



有时候人们会认为如果一个数据库只包含公开可用的数据,它就不需要保护。 这是不正确的。 即使允许在数据库中显示任何行,也应该防止拒绝服务攻击(例如,基于前一段中导致服务器浪费资源的技术的攻击)。 否则,您的服务器将无法响应合法用户。



检查列表:

  • 启用严格的SQL模式来告诉服务器对它接受的数据值有更多的限制。
  • 尝试在所有Web表单中输入单引号和双引号('和“)。如果遇到任何类型的MySQL错误,请立即调查问题。
  • 尝试通过向其添加%22(“),%23(#)和%27(')来修改动态网址。
  • 尝试使用前面示例中显示的字符将动态URL中的数据类型从数字修改为字符类型。 你的应用程序应该对这些和类似的攻击是安全的。
  • 尝试输入字符,空格和特殊符号,而不是数字字段中的数字。 在将应用程序传递给MySQL之前,您的应用程序应删除它们,否则会产生错误 ,将未经检查的值传递给MySQL是非常危险的!
  • 在传递给MySQL之前检查数据的大小。
  • 让您的应用程序使用与用于管理目的的用户名不同的用户名连接到数据库。 不要给你的应用程序任何他们不需要的访问权限。






许多应用程序编程接口提供了转义数据值中特殊字符的方法。 正确使用,这可以防止应用程序用户输入值导致应用程度产生不是你期望的其他语句:



  • MySQL C API:使用mysql_real_escape_string_quote()API调用。
  • MySQL ++:对查询流使用转义和引号修饰符。
  • PHP:使用mysqli或pdo_mysql扩展名,而不是旧的ext/mysql扩展名。 首选的API支持改进的MySQL身份验证协议和密码,以及带占位符的准备语句。




如果必须使用较旧的ext/mysql扩展,那么为了转义,使用mysql_real_escape_string_quote()函数而不是mysql_escape_string()或addslashes(),因为只有mysql_real_escape_string_quote()是可识别字符集的; 当使用(无效)多字节字符集时,其他函数可以被“绕过”。



  • Perl DBI:使用占位符或quote()方法。
  • Ruby DBI:使用占位符或quote()方法。
  • Java JDBC:使用PreparedStatement对象和占位符。




其他编程接口可能具有相似的功能。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69946831/viewspace-3119479/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-09-09

  • 博文量
    2646
  • 访问量
    42161