mita2 database life

主にMySQLに関するメモです

MySQL 8.0 の LOAD DATA で The used command is not allowed with this MySQL version エラー

TL;DR

  • MySQL 8.0 で LOAD DATA INFILE LOCAL を利用するには、
  • サーバとクライアント両方で local-infile パラメータを ON にする必要がある
  • セキュリティ強化のため、8.0から LOAD DATA INFILE LOCAL はデフォルトで無効にされた

MySQL 8.0 で LOAD DATA INFILE LOCAL が通らない

Loading local data is disabled; this must be enabled on both the client and server sides エラー*1LOAD DATA INFILE LOCAL が通らなくなっていた 。

mysql> LOAD DATA LOCAL INFILE 'file.csv' INTO TABLE tbl SET name=@1, created_at=@2;
ERROR 3948 (42000): Loading local data is disabled; this must be enabled on both the client and server sides

local-infile パラメータ

MySQL 8.0 で LOAD DATA LOCAL INFILE は無効化されたようです。 有効にするには、local-infileON に設定する必要があるようです。

ON にして試します。

mysql> SET GLOBAL local_infile=on; 
Query OK, 0 rows affected (0.00 sec)

mysql> LOAD DATA LOCAL INFILE 'file.csv' INTO TABLE tbl SET name=@1, created_at=@2;
ERROR 3948 (42000): Loading local data is disabled; this must be enabled on both the client and server sides

ダメでした。。。クライアント側でも--local-infileを有効化しないと、通らないようです。

$ mysql -h my8.local --local-infile=1
mysql>  LOAD DATA LOCAL INFILE 'file.csv' INTO TABLE tbl SET name=@1, created_at=@2;
Query OK, 2 rows affected, 10 warnings (0.05 sec)

行けました 👍

なぜ、無効化されたのか?

LOAD DATA LOCAL INFILE がデフォルトで無効化された理由はマニュアルに記載されています。

The transfer of the file from the client host to the server host is initiated by the MySQL server. In theory, a patched server could be built that would tell the client program to transfer a file of the server's choosing rather than the file named by the client in the LOAD DATA statement. Such a server could access any file on the client host to which the client user has read access. (A patched server could in fact reply with a file-transfer request to any statement, not just LOAD DATA LOCAL, so a more fundamental issue is that clients should not connect to untrusted servers.)

https://dev.mysql.com/doc/refman/8.0/en/load-data-local.html

LOAD DATA LOCAL INFILE ではSQL中でロードするファイル名を指定しているものの、実際は、サーバからクライアントに対して、ロードするファイルを指示する仕組みになっています。 悪意のある(改ざんされた)サーバに対して実行した場合、クライアントが指定したファイルと異なるファイルをサーバが指示して、送信させることが可能になってしまいます。

In a Web environment where the clients are connecting from a Web server, a user could use LOAD DATA LOCAL to read any files that the Web server process has read access to (assuming that a user could run any statement against the SQL server). In this environment, the client with respect to the MySQL server actually is the Web server, not a remote program being run by users who connect to the Web server.

もう1つ理由が述べられてます。 任意のSQLを実行できるようなWebアプリケーションを実装していた場合、LOAD DATA INFILE LOCAL を使って、任意のWebサーバ上のファイルを読み取ることが可能になってしまう。

例えば、SQLインジェクション脆弱性があった場合、DBのデータを操作されてしまうだけでなく、Webサーバ上のファイルの読み取りも許してしまうことに繋がってしまうということですね。

LOAD DATA INFILE LOCAL は セキュリティ上のリスクになる可能性があるということで、デフォルトで無効化されたことがわかりました。 使い続ける場合は、リスクを理解した上で利用する必要がありそうです。

*1:8.0.18までは The used command is not allowed with this MySQL version というエラー文言でした