实现原理:
攻击者搭建一个伪造的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来建立可信的连接。