1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

Compare commits

...

2 Commits

Author SHA1 Message Date
nnposter
472b586767 Refactor the script to address multiple issues
- Add support for HTTPS
  - Add support for IPv6
  - Add support for more than one path argument
  - Properly identify the Location header in the HTTP response
  - Properly identify the destination host in the Location header
  - Leverage normalized IP address comparison
  - Avoid processing the HTTP response body, possibly "endless"
  - Add the found IP address as a new scan target (optionally)
Close #3218, close #3191)
2025-12-02 23:55:01 +00:00
nnposter
306263da43 Explain the effect of arguments that are not script-specific. Close #3223, close #3221, fix #3211 2025-12-02 22:48:31 +00:00
3 changed files with 77 additions and 55 deletions

View File

@@ -1,5 +1,9 @@
#Nmap Changelog ($Id$); -*-text-*-
o [GH#3191][GH#3218] Script http-internal-ip-disclosure has been enhanced,
including added support for IPv6 and HTTPS and more accurate processing
of target responses. [nnposter]
o [GH#3194] RPC-based scripts were sporadically failing due to privileged
port conflicts. [nnposter]

View File

@@ -2480,9 +2480,20 @@ escapes a quote. A backslash is only used to escape quotation marks in this
special case; in all other cases a backslash is interpreted literally. Values
may also be tables enclosed in <literal>{}</literal>, just as in Lua. A table
may contain simple string values or more name-value pairs, including nested
tables. Many scripts qualify their arguments with the script name, as in <literal>xmpp-info.server_name</literal>. You may use that full qualified version to affect just the specified script, or you may pass the unqualified version (<literal>server_name</literal> in this case) to affect all scripts using that argument name. A script will first check for its fully qualified argument name (the name specified in its documentation) before it accepts an unqualified argument name. A complex example of script arguments is
<option>--script-args 'user=foo,pass=",{}=bar",whois={whodb=nofollow+ripe},xmpp-info.server_name=localhost'</option>. The online NSE Documentation Portal at <ulink url="https://nmap.org/nsedoc/"/>
lists the arguments that each script accepts.
tables. A complex example of script arguments is
<option>--script-args 'user=foo,pass=",{}=bar",whois={whodb=nofollow+ripe},xmpp-info.server_name=localhost'</option>.
Many scripts qualify their arguments with the script name, as in
<literal>xmpp-info.server_name</literal>. A script will first check for its
fully qualified argument name (the name specified in its documentation) before
it accepts an unqualified argument name (<literal>server_name</literal> in this
case). Some arguments are not specific to one script. They typically effect
behavior of a library and therefore potentially all the scripts that use the
library. (One such example is <literal>http.useragent</literal>, which sets
the default HTTP User-Agent header for every web request, regardless which
script sends it.) It is not possible for the exact same argument to be given
different values for diferent scripts. The online NSE Documentation Portal at
<ulink url="https://nmap.org/nsedoc/"/> lists the arguments that each script
accepts.
</para>
</listitem>
</varlistentry>

View File

@@ -1,21 +1,30 @@
local comm = require "comm"
local ipOps = require "ipOps"
local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
local ipOps = require "ipOps"
local target = require "target"
local url = require "url"
description = [[
Determines if the web server leaks its internal IP address when sending an HTTP/1.0 request without a Host header.
Determines if the web server leaks its internal IP address when sending
an HTTP/1.0 request without a Host header.
Some misconfigured web servers leak their internal IP address in the response
headers when returning a redirect response. This is a known issue for some
versions of Microsoft IIS, but affects other web servers as well.
If script argument <code>newtargets</code> is set, the script will
add the found IP address as a new target into the scan queue. (See
the documentation for NSE library <code>target</code> for details.)
]]
---
-- @usage nmap --script http-internal-ip-disclosure <target>
-- @usage nmap --script http-internal-ip-disclosure --script-args http-internal-ip-disclosure.path=/path <target>
-- @usage nmap --script http-internal-ip-disclosure --script-args http-internal-ip-disclosure.path=/mypath <target>
--
-- @args http-internal-ip-disclosure.path Path to URI. Default: /
-- @args http-internal-ip-disclosure.path Path (or a table of paths) to probe
-- Default: /
--
-- @output
-- 80/tcp open http syn-ack
@@ -27,61 +36,59 @@ versions of Microsoft IIS, but affects other web servers as well.
--
-- @see ssl-cert-intaddr.nse
author = "Josh Amishav-Zlatin"
author = {"Josh Amishav-Zlatin", "nnposter"}
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = { "vuln", "discovery", "safe" }
portrule = shortport.http
local function generateHttpV1_0Req(host, port, path)
local redirectIP, privateIP
local socket = nmap.new_socket()
socket:connect(host, port)
local cmd = "GET " .. path .. " HTTP/1.0\r\n\r\n"
socket:send(cmd)
while true do
local status, lines = socket:receive_lines(1)
if not status then
break
end
-- Check if the response contains a location header
if lines:match("Location") then
local locTarget = lines:match("Location: [%a%p%d]+")
-- Check if the redirect location contains an IP address
redirectIP = locTarget:match("[%d%.]+")
if redirectIP then
privateIP = ipOps.isPrivate(redirectIP)
end
stdnse.debug1("Location: %s", locTarget )
stdnse.debug1("Internal IP: %s", redirectIP )
end
end
socket:close()
-- Only report if the internal IP leaked is different then the target IP
if privateIP and redirectIP ~= host.ip then
return redirectIP
end
end
action = function(host, port)
local output = stdnse.output_table()
local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/"
local IP = generateHttpV1_0Req(host, port, path)
-- Check /images which is often vulnerable on some unpatched IIS servers
if not IP and path ~= "/images" then
path = "/images"
IP = generateHttpV1_0Req(host, port, path)
local patharg = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/"
if type(patharg) ~= "table" then
patharg = {patharg}
end
local paths = stdnse.output_table()
for _, path in ipairs(patharg) do
paths[path] = 1
end
paths["/images"] = 1
if IP then
output["Internal IP Leaked"] = IP
return output
local socket
local bopt = nil
local try = nmap.new_try(function () socket:close() end)
for path in pairs(paths) do
local req = "GET " .. path .. " HTTP/1.0\r\n\r\n"
local resp
if not bopt then
socket, resp, bopt = comm.tryssl(host, port, req)
if not socket then return end
else
try(socket:connect(host, port, bopt))
try(socket:send(req))
resp = ""
end
local findhead = function (s)
return s:find("\r?\n\r?\n")
end
if not findhead(resp) then
resp = resp .. try(socket:receive_buf(findhead, true))
end
socket:close()
local loc = resp:lower():match("\nlocation:[ \t]+(%S+)")
local lochost = url.parse(loc or "").host
if lochost and lochost ~= "" then
-- remove any IPv6 enclosure
lochost = lochost:gsub("^%[(.*)%]$", "%1")
if ipOps.isPrivate(lochost) and ipOps.compare_ip(lochost, "ne", host.ip) then
if target.ALLOW_NEW_TARGETS then
target.add(lochost)
end
local output = stdnse.output_table()
output["Internal IP Leaked"] = lochost
return output
end
end
end
end