Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

MySQL 8.3 Reference Manual  /  ...  /  Security Considerations for LOAD DATA LOCAL

8.1.6 LOAD DATA LOCAL 安全注意事项

LOAD DATA 语句将数据文件加载到表中。该语句可以加载服务器主机上的文件,也可以加载客户端主机上的文件,如果指定了 LOCAL 关键字。

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

  • 因为 LOAD DATA LOCAL 是一个 SQL 语句,解析发生在服务器端,并且从客户端主机到服务器主机的文件传输是由 MySQL 服务器发起的,该服务器告诉客户端程序传输语句中指定的文件。在理论上,一个修补的服务器可以告诉客户端程序传输服务器选择的文件,而不是语句中指定的文件。这样,服务器可以访问客户端主机上客户端用户有读取权限的任何文件。(一个修补的服务器实际上可以对任何语句(不仅仅是 LOAD DATA LOCAL)发出文件传输请求,因此更基本的问题是客户端不应该连接到不受信任的服务器。)

  • 在 Web 环境中,客户端来自 Web 服务器,在这种环境中,用户可以使用 LOAD DATA LOCAL 读取 Web 服务器进程有读取权限的任何文件(假设用户可以对 SQL 服务器运行任何语句)。在这种环境中,客户端相对于 MySQL 服务器实际上是 Web 服务器,而不是远程程序被用户连接到 Web 服务器。

为了避免连接到不受信任的服务器,客户端可以建立安全连接并使用 --ssl-mode=VERIFY_IDENTITY 选项和适当的 CA 证书来验证服务器身份。要实现这种级别的验证,必须首先确保服务器的 CA 证书可靠地提供给副本,否则将导致可用性问题。有关更多信息,请参阅 Command Options for Encrypted Connections

为了避免 LOAD DATA 问题,客户端应该避免使用 LOCAL,除非采取了适当的客户端预防措施。

为了控制本地数据加载,MySQL 允许启用或禁用该功能。MySQL 还允许客户端限制本地数据加载操作到指定目录中的文件。

启用或禁用本地数据加载功能

管理员和应用程序可以按照以下方式配置是否允许本地数据加载:

  • 在服务器端:

    • 系统变量 local_infile 控制服务器端的 LOCAL 功能。根据 local_infile 设置,服务器拒绝或允许客户端请求本地数据加载。

    • 默认情况下,local_infile 是禁用的。(这与 MySQL 的前版本不同。)要使服务器明确拒绝或允许 LOAD DATA LOCAL 语句(无论客户端程序和库如何在构建时或运行时配置),请使用 local_infile 禁用或启用 mysqldlocal_infile 也可以在运行时设置。

  • 在客户端:

    • ENABLED_LOCAL_INFILE CMake选项控制MySQL客户端库的编译默认 LOCAL功能(见第2.8.7节,“MySQL源配置选项”)。因此,客户端如果没有明确的安排,将根据ENABLED_LOCAL_INFILE设置在MySQL构建时指定的默认值启用或禁用 LOCAL功能。

    • 默认情况下,MySQL二进制分布中的客户端库是与ENABLED_LOCAL_INFILE禁用编译的。如果您从源代码编译MySQL,可以根据客户端是否应该禁用或启用 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脚本或其他读取选项文件的[client]组的程序中使用LOAD DATA LOCAL,可以在该组中添加一个local-infile选项设置。为了避免程序不理解该选项的问题,可以使用loose-前缀:

      [client]
      loose-local-infile=0

      或:

      [client]
      loose-local-infile=1
    • 在所有情况下,客户端成功使用本地加载操作还需要服务器允许本地加载。

如果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_options() C API函数的MYSQL_OPT_LOCAL_INFILEMYSQL_OPT_LOAD_DATA_LOCAL_DIR选项来控制哪些文件允许加载数据(见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值的方式如下:

    • 如果值为空指针(默认),那么它不命名任何目录,结果是没有文件被允许用于LOCAL数据加载。

    • 如果值是一个目录路径名,LOCAL数据加载是允许的,但仅限于位于命名目录中的文件。比较目录路径名和要加载的文件路径名是大小写敏感的,不管基础文件系统的大小写敏感性如何。

MySQL客户端程序使用以下mysql_options()选项:

  • 客户端mysql有一个--load-data-local-dir选项,该选项接受目录路径或空字符串。mysql使用选项值来设置MYSQL_OPT_LOAD_DATA_LOCAL_DIR选项(空字符串将值设置为空指针)。--load-data-local-dir选项的效果取决于LOCAL数据加载是否启用:

    --load-data-local-dir选项生效时,选项值指定了本地数据文件必须位于的目录。比较目录路径名和要加载的文件路径名是大小写敏感的,不管基础文件系统的大小写敏感性如何。如果选项值为空字符串,那么它不命名任何目录,结果是没有文件被允许用于本地数据加载。

  • mysqlimport为每个文件设置MYSQL_OPT_LOAD_DATA_LOCAL_DIR,以便目录包含文件是允许的本地加载目录。

  • 对于对应于LOAD DATA语句的数据加载操作,mysqlbinlog从二进制日志事件中提取文件,写入临时文件到本地文件系统,并写入LOAD DATA LOCAL语句,以便加载文件。默认情况下,mysqlbinlog将这些临时文件写入操作系统特定的目录。--local-load选项可以用于明确指定mysqlbinlog应该准备本地临时文件的目录。

    因为其他进程可以将文件写入默认的系统特定目录,因此建议指定--local-load选项以mysqlbinlog指定不同的目录用于数据文件,然后在处理mysqlbinlog的输出时指定同一个目录,方法是指定--load-data-local-dir选项到mysql

MySQL Shell 和本地数据加载

MySQL Shell 提供了一些实用程序来转储表、模式或服务器实例,并将其加载到其他实例中。当您使用这些实用程序处理数据时,MySQL Shell 提供了附加功能,例如输入预处理、多线程并行加载、文件压缩和解压缩,以及访问 Oracle Cloud Infrastructure Object Storage 存储桶的功能。为了获得最佳功能,请始终使用 MySQL Shell 的最新版本的转储和加载实用程序。

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 utility util.dumpSchemas(), and table dump utility util.dumpTables()

将实例、模式或表导出到一组转储文件中,然后可以使用 MySQL Shell 的转储加载实用程序将其上传到 MySQL 实例中。该实用程序提供 Oracle Cloud Infrastructure Object Storage 流式传输、MySQL HeatWave Service 兼容性检查和修改、以及执行 dry run 以标识问题的能力。

Dump loading utility util.loadDump()

将使用 MySQL Shell 的实例、模式或表转储实用程序创建的转储文件导入到 MySQL HeatWave Service DB System 或 MySQL 服务器实例中。该实用程序管理上传过程,提供远程存储的数据流式传输、表或表块的并行加载、进度状态跟踪、恢复和重置能力,以及并发加载的选项,同时转储仍在进行中。MySQL Shell 的并行表导入实用程序可以与转储加载实用程序结合使用,以在上传数据到目标 MySQL 实例之前修改数据。

有关实用程序的详细信息,请参阅 MySQL Shell 实用程序