6.1.6 LOAD DATA LOCAL 的安全注意事项
LOAD DATA语句将数据文件加载到 table 中。该语句可以加载服务器主机上的文件,或者,如果指定了LOCAL
关键字,则可以加载 Client 端主机上的文件。
LOAD DATA的LOCAL
版本存在两个潜在的安全问题:
-
由于本地加载数据是一条 SQL 语句,因此解析是在服务器端进行的,并且文件从 Client 端主机到服务器主机的传输是由 MySQL 服务器启动的,它将告诉 Client 端该语句中命名的文件。从理论上讲,打补丁的服务器可以告诉 Client 端程序传输服务器选择的文件,而不是语句中命名的文件。这样的服务器可以访问 Client 端用户具有读取权限的 Client 端主机上的任何文件。 (打补丁的服务器实际上可以用文件传输请求回复任何语句,而不仅仅是本地加载数据,因此更根本的问题是 Client 端不应连接到不受信任的服务器。)
-
在 Client 端从 Web 服务器连接的 Web 环境中,用户可以使用本地加载数据读取 Web 服务器进程具有读取权限的任何文件(假设用户可以对 SQL Server 运行任何语句)。在这种环境中,相对于 MySQL 服务器的 Client 端实际上是 Web 服务器,而不是由连接到 Web 服务器的用户运行的远程程序。
为了避免连接到不受信任的服务器,Client 端可以构建安全连接并通过使用--ssl-mode=VERIFY_IDENTITY选项和适当的 CA 证书进行连接来验证服务器身份。
为避免出现LOAD DATA问题,Client 应避免使用LOCAL
。
Management 员和应用程序可以配置是否允许本地数据加载,如下所示:
-
在服务器端:
-
local_infile系统变量控制服务器端
LOCAL
的功能。根据local_infile设置,服务器会拒绝或允许请求本地数据加载的 Client 端加载本地数据。- 默认情况下,禁用local_infile。要明确导致服务器拒绝或允许本地加载数据语句(无论在构建时或运行时如何配置 Client 端程序和库),请在禁用或启用local_infile的情况下启动mysqld。 local_infile也可以在运行时设置。
-
在 Client 端:
-
ENABLED_LOCAL_INFILE CMake 选项控制 MySQLClient 端库的内置默认
LOCAL
功能(请参阅第 2.9.7 节“ MySQL 源配置选项”)。因此,没有明确安排的 Client 端将根据 MySQL 构建时指定的ENABLED_LOCAL_INFILE设置禁用或启用LOCAL
功能。
-
默认情况下,MySQL 二进制发行版中的 Client 端库在启用ENABLED_LOCAL_INFILE的情况下进行编译。如果从源代码编译 MySQL,请根据未进行显式安排的 Client 端应禁用还是启用
LOCAL
功能,将ENABLED_LOCAL_INFILE禁用或启用。 -
对于使用 C API 的 Client 端程序,本地数据加载功能由编译到 MySQLClient 端库中的默认值决定。要显式启用或禁用它,请调用mysql_options() C API 函数以禁用或启用
MYSQL_OPT_LOCAL_INFILE
选项。参见第 27.7.6.50 节“ mysql_options()”。
- 对于mysqlClient 端,本地数据加载功能由编译到 MySQLClient 端库中的默认值决定。要显式禁用或启用它,请使用--local-infile=0或--local-infile[=1]选项。
- 对于mysqlimportClient 端,默认情况下不使用本地数据加载。要显式禁用或启用它,请使用--local=0或--local[=1]选项。
- 如果在 Perl 脚本或其他从选项文件中读取
[client]
组的程序中使用本地加载数据,则可以向该组添加local-infile
选项设置。为防止不了解此选项的程序出现问题,请使用loose-前缀指定它:
[client]
loose-local-infile=0
or:
[client]
loose-local-infile=1
- 在所有情况下,Client 端成功使用
LOCAL
加载操作还需要服务器允许本地加载。
如果禁用了LOCAL
功能,则在服务器或 Client 端上,尝试发出本地加载数据语句的 Client 端都会收到以下错误消息:
ERROR 1148: The used command is not allowed with this MySQL version