8.1.6 LOAD DATA LOCAL 安全性考虑
LOAD 数据语句将数据文件加载到表中。该语句可以从服务器主机或,如果指定了LOCAL
关键字,从客户端主机加载文件。
LOAD DATA LOCAL 版本有两个潜在的安全问题:
-
由于 LOAD 数据语句是 SQL 语句,解析发生在服务器端,而从客户端主机到服务器主机的文件传输由 MySQL 服务器初始化,这意味着服务器可以告诉客户端程序将指定的文件名传输,而不是实际要加载的文件。在理论上,一台被修补过的服务器可以告诉客户端程序传输它选择的文件,而不是语句中指定的文件。这样,服务器就可以访问客户端主机上的任何文件,以读取权限为准。 (一台被修补过的服务器实际上可以回复任何语句,而不仅限于 LOAD 数据 LOCAL,所以更基本的问题是客户端 shouldn't 连接到不可靠的服务器。)
-
在Web环境中,客户端从Web服务器连接到MySQL服务器时,可以使用
LOAD DATA LOCAL
读取Web服务器进程可以访问的任何文件(假设用户可以对SQL服务器运行任何语句)。在这个环境中,实际连接到MySQL服务器的是Web服务器,而不是由用户连接到Web服务器并运行远程程序的客户端。
为了避免连接到不受信任的服务器,客户端可以使用--ssl-mode=VERIFY_IDENTITY
选项和适当的CA证书来建立安全连接并验证服务器身份。要实现这个级别的验证,必须首先确保服务器的CA证书可靠地可供副本,否则将出现可用性问题。更多信息,请见Encrypted Connection Options。
为了避免LOAD DATA
问题,客户端应该避免使用LOCAL
,除非已经采取了适当的客户端安全措施。
为了控制本地数据加载,MySQL允许启用或禁用该能力。MySQL还允许客户端限制本地数据加载操作到指定目录中的文件。
管理员和应用程序可以按照以下方式配置是否允许本地数据加载:
-
在服务器端:
-
在客户端:
-
ENABLED_LOCAL_INFILE
CMake选项控制MySQL客户端库的编译时默认LOCAL
能力(见第2.8.7节,“MySQL源配置选项”)。没有明确安排的客户端因此具有LOCAL
能力禁用或启用,根据在MySQL构建时指定的ENABLED_LOCAL_INFILE
设置。 -
默认情况下,MySQL二进制分发中的客户端库是编译的
ENABLED_LOCAL_INFILE
禁用。如果您从源代码编译MySQL,configure它以ENABLED_LOCAL_INFILE
禁用或启用,以便客户端没有明确安排的LOCAL
能力是否禁用或启用。 -
使用C API的客户端程序的本地数据加载能力由MySQL客户端库编译时默认值确定。要显式启用或禁用,可以调用
mysql_options()
C API函数来禁用或启用MYSQL_OPT_LOCAL_INFILE
选项。见mysql_options(). -
mysql 客户端的本地数据加载能力由默认编译到 MySQL 客户端库中决定。要禁用或启用它,使用
--local-infile=0
或--local-infile[=1]
选项。 -
mysqlimport 客户端默认不使用本地数据加载。要禁用或启用它,使用
--local=0
或--local[=1]
选项。 -
如果您在 Perl 脚本或其他读取 option 文件的程序中使用
LOAD DATA LOCAL
,可以将local-infile
选项添加到该组中。为了防止不理解这个选项的程序出现问题,请使用loose-
前缀指定它:[client] loose-local-infile=0
或:
[client] loose-local-infile=1
-
在所有情况下,客户端成功使用
LOCAL
加载操作也需要服务器允许本地加载。
-
如果LOCAL
能力被禁用,服务器或客户端任一侧,一旦尝试执行LOAD DATA LOCAL
语句的客户端将收到以下错误消息:
ERROR 3950 (42000): Loading local data is disabled; this must be
enabled on both the client and server side
MySQL 客户库使客户应用程序可以限制本地数据加载操作到指定目录中的文件。某些 MySQL 客户端程序利用了这个能力。
使用 C API 的客户端程序可以使用MYSQL_OPT_LOCAL_INFILE
和MYSQL_OPT_LOAD_DATA_LOCAL_DIR
选项来控制 load data 加载的文件,通过mysql_options()
C API 函数(见mysql_options())。
MYSQL_OPT_LOAD_DATA_LOCAL_DIR
的效果取决于是否启用了LOCAL
数据加载:
-
如果启用了
LOCAL
数据加载,或者默认情况下 MySQL 客户库启用了它,或者显式地启用了MYSQL_OPT_LOCAL_INFILE
,那么MYSQL_OPT_LOAD_DATA_LOCAL_DIR
选项无效。 -
如果禁用了
LOCAL
数据加载,或者通过默认的MySQL客户端库或明确地禁用MYSQL_OPT_LOCAL_INFILE
,那么可以使用MYSQL_OPT_LOAD_DATA_LOCAL_DIR
选项来指定允许的本地加载文件目录。在这种情况下,LOCAL
数据加载被允许,但受限于位于指定目录中的文件。对MYSQL_OPT_LOAD_DATA_LOCAL_DIR
值的解释如下:-
如果值是null指针(默认),那么它不命名任何目录,结果是没有文件被允许用于
LOCAL
数据加载。 -
如果值是一个目录路径名称,
LOCAL
数据加载被允许,但受限于位于命名目录中的文件。无论底层文件系统的大小写敏感性如何,对目录路径名称和要加载的文件路径名称之间的比较都是大小写敏感的。
-
MySQL客户端程序使用前面的mysql_options()
选项如下:
-
MySQL 命令行客户端 mysql 有一个
--load-data-local-dir
选项,该选项可以传入目录路径或空字符串。mysql 使用选项值设置MYSQL_OPT_LOAD_DATA_LOCAL_DIR
选项(空字符串将设置该值为 null 指针)。--load-data-local-dir
选项的效果取决于是否启用LOCAL
数据加载:-
如果启用了
LOCAL
数据加载,或者默认情况下在 MySQL 客户端库中启用了该功能或指定了--local-infile[=1]
,则--load-data-local-dir
选项将被忽略。 -
如果禁用了
LOCAL
数据加载,或者默认情况下在 MySQL 客户端库中禁用该功能或指定了--local-infile=0
,则--load-data-local-dir
选项将生效。
当
--load-data-local-dir
生效时,选项值指定了本地数据文件必须位于的目录。无论底层文件系统是否区分大小写,该目录路径名称和要加载文件的路径名称之间的比较都是区分大小写的。如果选项值为空字符串,它将没有指定目录,从而不允许任何本地数据加载。 -
-
mysqlimport为每个文件设置
MYSQL_OPT_LOAD_DATA_LOCAL_DIR
-
对于对应于
LOAD DATA
语句的数据加载操作,mysqlbinlog从二进制日志事件中提取文件,将它们写入本地文件系统的临时文件,并将LOAD DATA LOCAL
语句写入,以便将文件加载。默认情况下,mysqlbinlog将这些临时文件写入操作系统特定的目录。可以使用--local-load
选项来明确指定mysqlbinlog应准备本地临时文件的目录。由于其他进程可能会将文件写入到默认的系统特定目录中,因此建议使用
--local-load
选项来指定mysqlbinlog的数据文件目录,然后使用--load-data-local-dir
选项来指定mysql处理来自mysqlbinlog的输出。
MySQL Shell 和本地数据加载
MySQL Shell 提供了多种工具来将表、模式或服务器实例dump到其他实例,并将其加载回去。当您使用这些工具处理数据时,MySQL Shell 还提供了额外的功能,如输入预处理、多线程并行加载、文件压缩和解压缩,以及访问 Oracle Cloud Infrastructure Object Storage 桶的权限。为了获得最佳的功能,请始终使用 MySQL Shell 的 dump 和 dump 加载工具的最新版本。
MySQL Shell的数据上传实用工具使用LOAD DATA LOCAL INFILE
语句上传数据,因此目标服务器实例上的local_infile
系统变量必须设置为ON
。您可以在上传数据前将其设置,并在完成后再次删除。实用工具安全地处理文件传输请求,以解决本主题中讨论的安全考虑问题。
MySQL Shell包含以下备份和恢复实用工具:
-
Table export utility
util.exportTable()
-
将 MySQL 关系表导出到数据文件,该文件可以使用 MySQL Shell 的并行表导入实用工具上传到 MySQL 服务器实例,导入到不同应用程序中或作为逻辑备份使用。该实用工具具有预置选项和自定义选项,可以生成不同的输出格式。
-
Parallel table import utility
util.importTable()
-
将数据文件导入到 MySQL 关系表中。数据文件可以是 MySQL Shell 的表导出实用工具的输出,也可以是支持实用工具预置和自定义选项的其他格式。该实用工具可以在添加数据到表之前对输入进行预处理,可以接受多个数据文件合并到单个关系表中,并自动解压缩压缩文件。
-
Instance dump utility
util.dumpInstance()
, schema dump utilityutil.dumpSchemas()
, and table dump utilityutil.dumpTables()
-
将实例、模式或表导出到一组덤프文件,然后使用 MySQL Shell 的dump加载实用工具上传到 MySQL 实例。实用工具提供 Oracle Cloud Infrastructure Object Storage 流式传输,MySQL HeatWave 服务兼容性检查和修改,以及在 dump 过程中执行 dry run,以识别问题并在继续 dump 前进行修复。
-
Dump loading utility
util.loadDump()
-
将使用 MySQL Shell 的实例、模式或表 dump 工具创建的备份文件导入到 MySQL HeatWave 服务 DB 系统或 MySQL 服务器实例中。该工具管理上传过程,并提供从远程存储中的数据流式传输、并行加载表或表块、进度状态跟踪、恢复和重置能力,以及在 dump 过程进行的并发加载选项。MySQL Shell 的并行表导入utility 可以与 dump 加载工具结合使用,以在将数据上传到目标 MySQL 实例之前修改数据。
有关工具的详细信息,请见MySQL Shell Utilities。