前两天在碰到一个Mysql root用户空口令并且允许远程连接。趁着这个机会开始练习使用Mysql相关的操作文件函数。

测试环境

  • CentOS 7 + Mysql 5.6
  • Mysql 用户有file权限

LOAD_FILE(file_name)

函数说明

Reads the file and returns the file contents as a string. To use this function, the file must be located on the server host, you mustspecify the full path name to the file, and you must have the FILE privilege. The file must be readable by all and its size less than max_allowed_packet bytes. If the secure_file_priv system variable is set to a nonempty directory name, the file to be loaded must be located in that directory. If the file does not exist or cannot be read because one of the preceding conditions is not satisfied, the function returns NULL.

读取文件并以文件内容作为字符串返回。说明如下:

  • 文件必须在服务器上
  • 必须知道文件的完整路径名
  • 必须有FILE权限
  • 文件必须可读
  • 文件大小必须小于max_allowed_packet
  • 如果secure_file_priv变量非空,文件必须在指定目录下
  • 文件不存在、文件不可读,返回值为NULL

自我理解

目标文件必须可读

文件属性分为三组,owner、group、other权限,目标文件必须可读含义为other权限必须为可读。

文件/tmp/test1.txt拥有者是mysql,权限为666,非同组的其他用户权限为可读可写。

1
2
3
4
5
mysql> SELECT * FROM test.test INTO OUTFILE '/tmp/test1.txt';
Query OK, 1 row affected
#ls -al |grep test1.txt
-rw-rw-rw- 1 mysql mysql 13 Oct 22 05:26 test1.txt

LOAD_FILE()读取成功

1
2
3
4
5
6
7
8
mysql> SELECT LOAD_FILE('/tmp/test1.txt');
+-----------------------------+
| LOAD_FILE('/tmp/test1.txt') |
+-----------------------------+
| admin 123456
|
+-----------------------------+
1 row in set

更改/tmp/test1.txt文件权限为660

1
2
3
# chmod 660 test1.txt
# ls -al |grep test1.txt
-rw-rw---- 1 mysql mysql 13 Oct 22 05:26 test1.txt

LOAD_FILE()读取失败

1
2
3
4
5
6
7
mysql> SELECT LOAD_FILE('/tmp/test1.txt');
+-----------------------------+
| LOAD_FILE('/tmp/test1.txt') |
+-----------------------------+
| NULL |
+-----------------------------+
1 row in set

在上述例子中,目标文件的拥有者均是mysql,不同结果说明对目标文件的要求是Other权限为可读,且LOAD_FILE()执行时不是以mysql用户。

SELECT … INTO OUTFILE file_name

函数说明

1
2
writes the selected rows to a file. Column and line terminators can be specified to
produce a specific output format.

把所选的多列写进文件,并且可以指定格式。

自我理解

默认输出到当前数据库所在目录

1
2
3
4
5
6
7
8
9
# ls -al
total 110616
...
drwx------. 2 mysql mysql 4096 Oct 21 18:08 performance_schema
drwx------ 2 mysql mysql 66 Oct 21 23:31 test
...
mysql> SELECT * FROM test.test INTO OUTFILE 'h.txt';
Query OK, 1 row affected

数据库的数据存放路径/var/lib/mysql/database_name/,例子中操作的数据库是test,路径是/var/lib/mysql/test/,其中test目录权限仅为mysql用户可读可写可执行。
写入成功

1
2
# ls
db.opt h.txt test.frm test.ibd

说明OUTFILE函数执行时,用户身份是mysql。

题外话

  • Mysql运行时,必须以root身份运行
  • Mysql system函数,执行shell命令时,是以本地执行环境有关,与远程服务器无关,故有些使用system函数提权的说法并不准确
  • 可以使用LOAD_FILE()函数查看服务器大部分文件,比如www目录下的文件,其实在实际中最大的障碍是无法获取网站的绝对路径。
  • 在知道网站绝对路径下,可以使用OUTFILE函数导出一句话木马
  • 所为的这些已经很老套的入侵方法,其实和Mysql的特性有着极大的关系,换一个角度看待问题,而不是总是想着哪个函数可以getshell,以程序员的眼光看待,以黑客的角度思考
  • 下周总结Mysql数据库脱裤的几种方法