CTF 漏洞复现

Mysql任意文件读取漏洞

Posted on 2020-01-19,4 min read

实现原理:
攻击者搭建一个伪造的mysql服务器,当有用户去连接上这个伪造的服务器时。
攻击者就可以任意读取受害者的文件内容。
具体可以去看下Mysql连接时的流量。会有一个load_file命令。因为我们是服务端。可以自定义这个命令。就实现了任意文件读取。

具体原理参考:https://cloud.tencent.com/developer/article/1426503
实验一
用到的工具:https://github.com/allyshka/Rogue-MySql-Server.git
这里用到两台机子。
Kali:192.168.0.138(伪造服务端)
Centos:192.168.0.131(伪造客户端)
修改脚本。读取/etc/passwd

启动。在Kali上。开了个3306端口。这个端口也可以自定义修改

然后受害者去连接Kali的Mysql服务。用户名密码甜不甜都无所谓的。脚本中。没有验证。

回到Kali。可以看到已经读取到了passwd文件

接着来说下实际环境中。此漏洞的意义。
1。配合phpmyadmin任意文件读取
phpmyadmin默认是没有服务器地址选项的。需要修改配置phpMyAdmin\libraries\config.default.php

$cfg['AllowArbitraryServer'] = true;


由于。这里我用的是windows。所以。服务端文件。改为了自定义的flag

登陆后。拿到flag

2。配合CMS重装漏洞。在填写配置的时候。将数据库填为我们恶意的服务端。就达到了文件读取
下面是DDCTF2019的题
地址:http://117.51.147.155:5000/index.html#/scan

看agent.py是个啥

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 12/1/2019 2:58 PM
# @Author  : fz
# @Site    : 
# @File    : agent.py
# @Software: PyCharm

import json
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from optparse import OptionParser
from subprocess import Popen, PIPE


class RequestHandler(BaseHTTPRequestHandler):

    def do_GET(self):
        request_path = self.path

        print("\n----- Request Start ----->\n")
        print("request_path :", request_path)
        print("self.headers :", self.headers)
        print("<----- Request End -----\n")

        self.send_response(200)
        self.send_header("Set-Cookie", "foo=bar")
        self.end_headers()

        result = self._func()
        self.wfile.write(json.dumps(result))


    def do_POST(self):
        request_path = self.path

        # print("\n----- Request Start ----->\n")
        print("request_path : %s", request_path)

        request_headers = self.headers
        content_length = request_headers.getheaders('content-length')
        length = int(content_length[0]) if content_length else 0

        # print("length :", length)

        print("request_headers : %s" % request_headers)
        print("content : %s" % self.rfile.read(length))
        # print("<----- Request End -----\n")

        self.send_response(200)
        self.send_header("Set-Cookie", "foo=bar")
        self.end_headers()
        result = self._func()
        self.wfile.write(json.dumps(result))

    def _func(self):
        netstat = Popen(['netstat', '-tlnp'], stdout=PIPE)
        netstat.wait()

        ps_list = netstat.stdout.readlines()
        result = []
        for item in ps_list[2:]:
            tmp = item.split()
            Local_Address = tmp[3]
            Process_name = tmp[6]
            tmp_dic = {'local_address': Local_Address, 'Process_name': Process_name}
            result.append(tmp_dic)
        return result

    do_PUT = do_POST
    do_DELETE = do_GET


def main():
    port = 8123
    print('Listening on localhost:%s' % port)
    server = HTTPServer(('0.0.0.0', port), RequestHandler)
    server.serve_forever()


if __name__ == "__main__":
    parser = OptionParser()
    parser.usage = (
        "Creates an http-server that will echo out any GET or POST parameters, and respond with dummy data\n"
        "Run:\n\n")
    (options, args) = parser.parse_args()

    main()

总结一下:这脚本就是放在你要扫描的服务器上。运行就会开一个8123端口。然后通过netstat -ntlp。将本机上开的服务都输出出来

然后通过主页上的IP。端口。去探测Mysql弱口令。
那我们将这脚本。放在VPS上。然后再开启mysql的服务端。IP。端口都填VPS。不就好了

flag在~/.mysql_history中。
一般就是重要的配置文件。passwd。history。
防御手段
避免使用 local读取本地文件
使用 --ssl-mode=VERIFY_IDENTITY来建立可信的连接。

下一篇: 2016 0CTF—piapiapia→