9.8 High
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
HIGH
CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
10 High
CVSS2
Access Vector
NETWORK
Access Complexity
LOW
Authentication
NONE
Confidentiality Impact
COMPLETE
Integrity Impact
COMPLETE
Availability Impact
COMPLETE
AV:N/AC:L/Au:N/C:C/I:C/A:C
0.973 High
EPSS
Percentile
99.8%
Lists the geographic locations of each hop in a traceroute and optionally saves the results to a KML file, plottable on Google earth and maps.
full path and name of file to write KML data to. The KML file can be used in Google earth or maps to plot the traceroute data.
See the documentation for the slaxml library.
See the documentation for the http library.
See the documentation for the smbauth library.
nmap --traceroute --script traceroute-geolocation
| traceroute-geolocation:
| hop RTT ADDRESS GEOLOCATION
| 1 ...
| 2 ...
| 3 ...
| 4 ...
| 5 16.76 e4-0.barleymow.stk.router.colt.net (194.68.128.104) 62,15 Sweden (Unknown)
| 6 48.61 te0-0-2-0-crs1.FRA.router.colt.net (212.74.65.49) 54,-2 United Kingdom (Unknown)
| 7 57.16 87.241.37.146 42,12 Italy (Unknown)
| 8 157.85 212.162.64.146 42,12 Italy (Unknown)
| 9 ...
|_ 10 ...
local http = require "http"
local io = require "io"
local json = require "json"
local stdnse = require "stdnse"
local tab = require "tab"
local table = require "table"
local ipOps = require "ipOps"
description = [[
Lists the geographic locations of each hop in a traceroute and optionally
saves the results to a KML file, plottable on Google earth and maps.
]]
---
-- @usage
-- nmap --traceroute --script traceroute-geolocation
--
-- @output
-- | traceroute-geolocation:
-- | hop RTT ADDRESS GEOLOCATION
-- | 1 ...
-- | 2 ...
-- | 3 ...
-- | 4 ...
-- | 5 16.76 e4-0.barleymow.stk.router.colt.net (194.68.128.104) 62,15 Sweden (Unknown)
-- | 6 48.61 te0-0-2-0-crs1.FRA.router.colt.net (212.74.65.49) 54,-2 United Kingdom (Unknown)
-- | 7 57.16 87.241.37.146 42,12 Italy (Unknown)
-- | 8 157.85 212.162.64.146 42,12 Italy (Unknown)
-- | 9 ...
-- |_ 10 ...
-- @xmloutput
-- <table>
-- <elem key="hop">1</elem>
-- </table>
-- <table>
-- <elem key="hop">2</elem>
-- </table>
-- <table>
-- <elem key="hop">3</elem>
-- </table>
-- <table>
-- <elem key="hop">4</elem>
-- </table>
-- <table>
-- <elem key="hop">5</elem>
-- <elem key="rtt">16.76</elem>
-- <elem key="ip">194.68.128.104</elem>
-- <elem key="hostname">e4-0.barleymow.stk.router.colt.net</elem>
-- <elem key="lat">62</elem>
-- <elem key="lon">15</elem>
-- </table>
-- <table>
-- <elem key="hop">6</elem>
-- <elem key="rtt">48.61</elem>
-- <elem key="ip">212.74.65.49</elem>
-- <elem key="hostname">te0-0-2-0-crs1.FRA.router.colt.net</elem>
-- <elem key="lat">54</elem>
-- <elem key="lon">-2</elem>
-- </table>
--
-- @args traceroute-geolocation.kmlfile full path and name of file to write KML
-- data to. The KML file can be used in Google earth or maps to plot the
-- traceroute data.
--
author = "Patrik Karlsson"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"safe", "external", "discovery"}
local arg_kmlfile = stdnse.get_script_args(SCRIPT_NAME .. ".kmlfile")
hostrule = function(host)
if ( not(host.traceroute) ) then
return false
end
return true
end
--
-- GeoPlugin requires no API key and has no limitations on lookups
--
local function geoLookup(ip, no_cache)
local output = stdnse.registry_get({SCRIPT_NAME, ip})
if output then return output end
local response = http.get("www.geoplugin.net", 80, "/json.gp?ip="..ip, {any_af=true})
local stat, loc = json.parse(response.body)
local get_value = function (d)
local t = type(d)
return (t == "string" or t == "number") and d or nil
end
if not (stat
and get_value(loc.geoplugin_latitude)
and get_value(loc.geoplugin_longitude)) then
return nil
end
output = {
lat = loc.geoplugin_latitude,
lon = loc.geoplugin_longitude,
reg = get_value(loc.geoplugin_regionName) or "Unknown",
ctry = get_value(loc.geoplugin_countryName) or "Unknown"
}
if not no_cache then
stdnse.registry_add_table({SCRIPT_NAME}, ip, output)
end
return output
end
local function createKMLFile(filename, coords)
local header = '<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://earth.google.com/kml/2.0"><Document><Placemark><LineString><coordinates>\r\n'
local footer = '</coordinates></LineString><Style><LineStyle><color>#ff0000ff</color></LineStyle></Style></Placemark></Document></kml>'
local output = {}
for _, coord in ipairs(coords) do
output[#output+1] = ("%s,%s, 0.\r\n"):format(coord.lon, coord.lat)
end
local f = io.open(filename, "w")
if ( not(f) ) then
return false, "Failed to create KML file"
end
f:write(header .. table.concat(output) .. footer)
f:close()
return true
end
-- Tables used to accumulate output.
local output_structured = {}
local output = tab.new(4)
local coordinates = {}
local function output_hop(count, ip, name, rtt, geo)
if ip then
local label
if name then
label = ("%s (%s)"):format(name or "", ip)
else
label = ("%s"):format(ip)
end
if geo then
table.insert(output_structured, { hop = count, ip = ip, hostname = name, rtt = ("%.2f"):format(rtt), lat = geo.lat, lon = geo.lon })
tab.addrow(output, count, ("%.2f"):format(rtt), label, ("%.3f,%.3f %s (%s)"):format(geo.lat, geo.lon, geo.ctry, geo.reg))
table.insert(coordinates, { hop = count, lat = geo.lat, lon = geo.lon })
else
table.insert(output_structured, { hop = count, ip = ip, hostname = name, rtt = ("%.2f"):format(rtt) })
tab.addrow(output, count, ("%.2f"):format(rtt), label, ("%s,%s"):format("- ", "- "))
end
else
table.insert(output_structured, { hop = count })
tab.addrow(output, count, "...")
end
end
action = function(host)
tab.addrow(output, "HOP", "RTT", "ADDRESS", "GEOLOCATION")
for count = 1, #host.traceroute do
local hop = host.traceroute[count]
-- avoid timedout hops, marked as empty entries
-- do not add the current scanned host.ip
if hop.ip then
local rtt = tonumber(hop.srtt) * 1000
local geo
if not ipOps.isPrivate(hop.ip) then
-- be sure not to cache the target address, since it's not likely to be
-- a hop for something else.
geo = geoLookup(hop.ip, ipOps.compare_ip(hop.ip, "eq", host.ip) )
end
output_hop(count, hop.ip, hop.name, rtt, geo)
else
output_hop(count)
end
end
if (#output_structured > 0) then
output = tab.dump(output)
if ( arg_kmlfile ) then
if ( not(createKMLFile(arg_kmlfile, coordinates)) ) then
output = output .. ("\n\nERROR: Failed to write KML to file: %s"):format(arg_kmlfile)
end
end
return output_structured, stdnse.format_output(true, output)
end
end
9.8 High
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
HIGH
CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
10 High
CVSS2
Access Vector
NETWORK
Access Complexity
LOW
Authentication
NONE
Confidentiality Impact
COMPLETE
Integrity Impact
COMPLETE
Availability Impact
COMPLETE
AV:N/AC:L/Au:N/C:C/I:C/A:C
0.973 High
EPSS
Percentile
99.8%