Lucene search

K
nmapPatrik KarlssonNMAP:TRACEROUTE-GEOLOCATION.NSE
HistoryApr 17, 2012 - 7:39 p.m.

traceroute-geolocation NSE Script

2012-04-1719:39:27
Patrik Karlsson
nmap.org
209

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.

Script Arguments

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.

slaxml.debug

See the documentation for the slaxml library.

http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent

See the documentation for the http library.

smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername

See the documentation for the smbauth library.

Example Usage

nmap --traceroute --script traceroute-geolocation

Script 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   ...

Requires


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%

Related for NMAP:TRACEROUTE-GEOLOCATION.NSE