Skip to content

Commit

Permalink
Provides a common function, url.get_default_port(), for obtaining
Browse files Browse the repository at this point in the history
the default port number for a given scheme. Fixes nmap#781
  • Loading branch information
nnposter committed Apr 19, 2017
1 parent af6bbc3 commit e80976a
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 77 deletions.
6 changes: 4 additions & 2 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Nmap Changelog ($Id$); -*-text-*-

o [NSE][GH#781] There is a new common function, url.get_default_port(),
to obtain the default port number for a given scheme. [nnposter]

o [NSE][GH#833] Function url.parse() now returns the port part as a number,
not a string, which eliminates various inconsistencies in scripts that
consume the function. [nnposter]
not a string. [nnposter]

o [NSE][GH#854] New script smb-double-pulsar-backdoor detects the Shadow
Brokers-leaked Double Pulsar backdoor in Windows SMB servers. [Andrew Orr]
Expand Down
6 changes: 2 additions & 4 deletions nselib/data/http-default-accounts-fingerprints.lua
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,8 @@ local function url_build_defaults (host, port, parsed)
local parts = tcopy(parsed or {})
parts.host = parts.host or stdnse.get_hostname(host, port)
parts.scheme = parts.scheme or shortport.ssl(host, port) and "https" or "http"
local pn = parts.port or port.number
if not (parts.scheme == "http" and pn == 80
or parts.scheme == "https" and pn == 443) then
parts.port = pn
if not parts.port and port.number ~= url.get_default_port(parts.scheme) then
parts.port = port.number
end
return parts
end
Expand Down
37 changes: 11 additions & 26 deletions nselib/http.lua
Original file line number Diff line number Diff line change
Expand Up @@ -157,19 +157,23 @@ local function table_augment(to, from)
end
end

--- Provide the default port for a given scheme.
-- The localization is necessary because functions in http.lua like to use
-- "url" as a local parameter
local get_default_port = url.get_default_port

--- Get a value suitable for the Host header field.
-- See RFC 2616 sections 14.23 and 5.2.
local function get_host_field(host, port)
if not host then return nil end
if type(port) == "number" then
port = {number=port, protocol="tcp", state="open", version={}}
end
local ssl = shortport.ssl(host, port)
local pn = port.number
if not ssl and pn == 80 or ssl and pn == 443 then
local scheme = shortport.ssl(host, port) and "https" or "http"
if port.number == get_default_port(scheme) then
return stdnse.get_hostname(host)
else
return stdnse.get_hostname(host) .. ":" .. pn
return stdnse.get_hostname(host) .. ":" .. port.number
end
end

Expand Down Expand Up @@ -1496,14 +1500,7 @@ local redirect_ok_rules = {
function (url, host, port)
-- port fixup, adds default ports 80 and 443 in case no url.port was
-- defined, we do this based on the url scheme
local url_port = url.port
if ( not(url_port) ) then
if ( url.scheme == "http" ) then
url_port = 80
elseif( url.scheme == "https" ) then
url_port = 443
end
end
local url_port = url.port or get_default_port(url.scheme)
if not url_port or url_port == port.number then
return true
end
Expand Down Expand Up @@ -1581,11 +1578,7 @@ function parse_redirect(host, port, path, response)
u.path = ((u.path:sub(1,1) == "/" and "" ) or "/" ) .. u.path -- ensuring leading slash
end
-- do port fixup
if ( not(u.port) ) then
if ( u.scheme == "http" ) then u.port = 80
elseif ( u.scheme == "https") then u.port = 443
else u.port = port.number end
end
u.port = u.port or get_default_port(u.scheme) or port.number
if ( not(u.path) ) then
u.path = "/"
end
Expand Down Expand Up @@ -1679,15 +1672,7 @@ function get_url( u, options )
local port = {}

port.service = parsed.scheme
port.number = parsed.port

if not port.number then
if parsed.scheme == 'https' then
port.number = 443
else
port.number = 80
end
end
port.number = parsed.port or get_default_port(parsed.scheme) or 80

local path = parsed.path or "/"
if parsed.query then
Expand Down
13 changes: 2 additions & 11 deletions nselib/httpspider.lua
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,7 @@ LinkExtractor = {
base_href = base_href .. '/'
end

if ( ( base_url:getProto() == 'https' and base_url:getPort() == 443 ) or
( base_url:getProto() == 'http' and base_url:getPort() == 80 ) ) then

if base_url:getPort() == url.get_default_port(base_url:getProto()) then
if ( leading_slash ) then
return ("%s://%s/%s"):format(base_url:getProto(), base_url:getHost(), rel_url)
else
Expand Down Expand Up @@ -427,14 +425,7 @@ URL = {
self.proto, self.host, self.port, self.file = self.raw:match("^(http[s]?)://([^:/]*)[:]?(%d*)")
if ( self.proto and self.host ) then
self.file = self.raw:match("^http[s]?://[^:/]*[:]?%d*(/[^#]*)") or '/'
self.port = tonumber(self.port)
if ( not(self.port) ) then
if ( self.proto:match("https") ) then
self.port = 443
elseif ( self.proto:match("http")) then
self.port = 80
end
end
self.port = tonumber(self.port) or url.get_default_port(self.proto)

self.path = self.file:match("^([^?]*)[%?]?")
self.dir = self.path:match("^(.+%/)") or "/"
Expand Down
12 changes: 12 additions & 0 deletions nselib/url.lua
Original file line number Diff line number Diff line change
Expand Up @@ -373,4 +373,16 @@ function build_query(query)
return table.concat(qstr, '&')
end

---
-- Provides the default port for a given URI scheme.
--
-- @param scheme for determining the port, such as "http" or "https".
-- @return A port number as an integer, such as 443 for scheme "https",
-- or nil in case of an undefined scheme
-----------------------------------------------------------------------------
function get_default_port (scheme)
local ports = {http=80, https=443}
return ports[(scheme or ""):lower()]
end

return _ENV;
9 changes: 2 additions & 7 deletions scripts/http-backup-finder.nse
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,8 @@ action = function(host, port)
if ( parsed.path:match(".*%.*.$") ) then
-- iterate over possible backup files
for link in backupNames(parsed.path) do
local host, port = parsed.host, parsed.port

-- if no port was found, try to deduce it from the scheme
if ( not(port) ) then
port = (parsed.scheme == 'https') and 443
port = port or ((parsed.scheme == 'http') and 80)
end
local host = parsed.host
local port = parsed.port or url.get_default_port(parsed.scheme)

-- the url.escape doesn't work here as it encodes / to %2F
-- which results in 400 bad request, so we simple do a space
Expand Down
10 changes: 3 additions & 7 deletions scripts/http-favicon.nse
Original file line number Diff line number Diff line change
Expand Up @@ -128,21 +128,17 @@ end
-- host, port, and path if the URL is relative. Return nil if the scheme is not
-- "http" or "https".
function parse_url_relative(u, host, port, path)
local defaultport, scheme, abspath
local scheme, abspath
u = url.parse(u)
scheme = u.scheme or "http"
if scheme == "http" then
defaultport = 80
elseif scheme == "https" then
defaultport = 443
else
if not (scheme == "http" or scheme == "https") then
return nil
end
abspath = u.path or ""
if not string.find(abspath, "^/") then
abspath = dirname(path) .. "/" .. abspath
end
return u.host or host, u.port or defaultport, abspath
return u.host or host, u.port or url.get_default_port(scheme), abspath
end

function parseIcon( body )
Expand Down
8 changes: 1 addition & 7 deletions scripts/http-open-redirect.nse
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,7 @@ local function dbgt(tbl)
end

local function getHostPort(parsed)
local host, port = parsed.host, parsed.port
-- if no port was found, try to deduce it from the scheme
if ( not(port) ) then
port = (parsed.scheme == 'https') and 443
port = port or ((parsed.scheme == 'http') and 80)
end
return host, port
return parsed.host, parsed.port or url.get_default_port(parsed.scheme)
end

local function isRedirect(status)
Expand Down
8 changes: 2 additions & 6 deletions scripts/http-phpself-xss.nse
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,8 @@ PHP files are not handling safely the variable $_SERVER["PHP_SELF"] causing Refl

--Only work with .php files
if ( parsed.path and parsed.path:match(".*.php") ) then
--The following port/scheme code was seen in http-backup-finder and its neat =)
local host, port = parsed.host, parsed.port
if ( not(port) ) then
port = (parsed.scheme == 'https') and 443
port = port or ((parsed.scheme == 'http') and 80)
end
local host = parsed.host
local port = parsed.port or url.get_default_port(parsed.scheme)
local escaped_link = parsed.path:gsub(" ", "%%20")
if launch_probe(host,port,escaped_link) then
table.insert(vulnpages, parsed.scheme..'://'..host..escaped_link..PHP_SELF_PROBE)
Expand Down
9 changes: 2 additions & 7 deletions scripts/http-unsafe-output-escaping.nse
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,9 @@ portrule = shortport.http
local dbg = stdnse.debug2

local function getHostPort(parsed)
local host, port = parsed.host, parsed.port
-- if no port was found, try to deduce it from the scheme
if ( not(port) ) then
port = (parsed.scheme == 'https') and 443
port = port or ((parsed.scheme == 'http') and 80)
end
return host, port
return parsed.host, parsed.port or url.get_default_port(parsed.scheme)
end

local function getReflected(parsed, r)
local reflected_values,not_reflected_values = {},{}
local count = 0
Expand Down

0 comments on commit e80976a

Please sign in to comment.