Skip to content

Latest commit

 

History

History
154 lines (77 loc) · 4.38 KB

README.md

File metadata and controls

154 lines (77 loc) · 4.38 KB

ApricusFakemysql

这是一个完全用go实现的fakemysql工具

利用

mysql local infile 读取

mysql jdbc 反序列化漏洞 RCE

mysql postgresql 反序列化漏洞 RCE

特点

1.支持文件名加密

2.支持大文件传输[取决于你的运行内存,应该能轻松1个g]

3.支持navicat[不管什么版本]

4.payload支持

点子

1.对于greeting的发包的mysql版本会随机发送版本

2.文件名支持加密防止特殊符号

运行测试

利用成功【测试环境 java1.8+mysql-connector-java 8/5.1.27】

note笔记

记录ApricusFakemysql中开发中学习的内容和遇到实现难点

构造服务端通信包

首先分析mysql初始发包到服务端,抓包分析

mysqlpacket_1

可以看到以下几步

1、greeting包,服务端返回了banner,其中包含mysql的版本

2、客户端登录请求

3、初始化查询

为了要实现一个fake mysql,需要自主构造greeting

分析greeting

4字节的包头 + 若干字节的包体。

解析包头字段:
 3字节:包体的有效长度,小端格式。
 1字节:包号。由于有效长度最大只能表示16M长度,所以增加一个包号字段,循环使用。

解析包体字段:
 1字节:协议版本号。
 若干字节:以0x00结尾的服务器版本描述。
 4字节:连接mysql使用的线程ID。
 9字节:8字节用于安全认证的随机数,+1字节的0x00填充。
 2字节:服务器能力标志集合。
 1字节:服务器默认使用的字符编码。
 2字节:服务器状态标志集合。
 13字节:保留。
 13字节:12字节用于安全认证的随机数补充,+1字节的0x00填充。
 若干字节:以0x00结尾的若干警告或其他描述文本。

关于安全认证的随机数:
 考虑到兼容性,随机数被分成2部分,旧版本使用8字节的随机数,新版本使用20字节的随机数。
 
看下面得结构更简洁
 
协议号 - Int<1> (Protocol number – Int<1>)
服务端版本号 - String (Server version – String)
线程 id - Int<4> (Thread id – Int<4>)
盐值1 - String (Salt1 – String)
服务端能力 - Int<2> (Server capabilities – Int<2>)
服务端语言 - Int<1> (Server language – Int<1>)
服务端状态 - Int<2> (Server Status – Int<2>)
扩展服务端能力 - Int<2> (Extended Server Capabilities – Int<2>)
身份认证插件长度 - Int<1> (Authentication plugin length – Int<1>)
保留字节 - 10 字节 (Reserved bytes – 10 bytes)
盐值2 - String (Salt2 – String)
身份验证插件字符串 - String (Authentication plugin string – String)

其中navicat的插件authplugin有区别,在返回相应包的时候需要返回切换插件的请求,也就是这点是通过用户输入请求是否包含“@clear”和客户端返回的插件同时判断的

image-20231118093810618

image-20231118094016678

而切换的数据包也十分好构造,返回eof数据包同时写入auth method name

客户端登录请求更简单,通过这个就明白了

image-20231118094311413

之后进行循环处理客户端请求,对于readfile来说,构造一个oxfb 返回code的packet和文件也是很简单的。

image-20231118102236925

可以看到local读取成功

image-20231118102134738

修改后能处理大文件了,只要不超过go的byte数组限制,也就是你运行的最大内存,这也是个很大的数字了,下面写实现读取大文件的思路

读取大文件

读取大文件此处有点难度

由于始终是读取mysql proto类型的包,需要写一个mysql packet的结构体,isEnd作为符号符,由于go中io.reader接口有con,直接设置mysql流类型为io.reaeder,每个数据包根据前面length判断,如果是个满的数据包,也就是

image-20231119141807431

8192,说明包没读完,设置follow也就是跟随符号符是否继续下一个包的读取,之后循环读取包数据存在byte数组里。这里我尝试了100mb文件传输依旧没有任何问题。