mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31:29 +00:00
New scripts for geo mapping. Closes #606
This commit is contained in:
182
scripts/ip-geolocation-map-google.nse
Normal file
182
scripts/ip-geolocation-map-google.nse
Normal file
@@ -0,0 +1,182 @@
|
||||
local http = require "http"
|
||||
local geoip = require "geoip"
|
||||
local io = require "io"
|
||||
local stdnse = require "stdnse"
|
||||
local table = require "table"
|
||||
local url = require "url"
|
||||
|
||||
description = [[
|
||||
This script queries the Nmap registry for the GPS coordinates of targets stored
|
||||
by previous geolocation scripts and renders a Google Map of markers representing
|
||||
the targets.
|
||||
|
||||
Additional information for the Google Static Maps API can be found at:
|
||||
- https://developers.google.com/maps/documentation/static-maps/intro
|
||||
]]
|
||||
|
||||
---
|
||||
-- @usage
|
||||
-- nmap -sn -Pn --script ip-geolocation-geoplugin,ip-geolocation-map-google --script-args ip-geolocation-map-google.api_key=[redacted],ip-geolocation-map-google.map_path=map.png <target>
|
||||
--
|
||||
-- @output
|
||||
-- | ip-geolocation-map-google:
|
||||
-- |_ The map has been saved at 'map.png'.
|
||||
--
|
||||
-- @args ip-geolocation-map-google.api_key The required Google Maps API key for
|
||||
-- your account. An API key can be generated at
|
||||
-- https://developers.google.com/maps/documentation/static-maps/." @args
|
||||
--
|
||||
-- ip-geolocation-map-google.center GPS coordinates defining the center of the
|
||||
-- image. If omitted, Google Maps will choose a center that shows all the
|
||||
-- markers.
|
||||
--
|
||||
-- @args ip-geolocation-map-google.format The default value is 'png' (alias for
|
||||
-- 'png8'), 'png32', 'gif', 'jpg', and 'jpg-baseline' are also allowed.
|
||||
-- https://developers.google.com/maps/documentation/static-maps/intro#ImageFormats
|
||||
--
|
||||
-- @args ip-geolocation-map-google.language The default value is 'en', but other
|
||||
-- two-letter language codes are accepted.
|
||||
--
|
||||
-- @args ip-geolocation-map-google.layer The default value is 'roadmap',
|
||||
-- 'satellite', 'hybrid', and 'terrain' are also allowed.
|
||||
-- https://developers.google.com/maps/documentation/static-maps/intro#MapTypes
|
||||
--
|
||||
-- @args ip-geolocation-map-google.map_path The path at which the rendered
|
||||
-- Google Map will be saved to the local filesystem.
|
||||
--
|
||||
-- @args ip-geolocation-map-google.marker_style This argument can apply styling
|
||||
-- to the markers.
|
||||
-- https://developers.google.com/maps/documentation/static-maps/intro#MarkerStyles
|
||||
--
|
||||
-- @args ip-geolocation-map-google.scale The default value is 1, but values 2
|
||||
-- and 4 are permitted. Scale level 4 is only available to Google Maps Premium
|
||||
-- customers.
|
||||
-- https://developers.google.com/maps/documentation/static-maps/intro#scale_values
|
||||
--
|
||||
-- @args ip-geolocation-map-google.size The default value is '640x640' pixels,
|
||||
-- but can be increased by Google Maps Premium customers.
|
||||
-- https://developers.google.com/maps/documentation/static-maps/intro#Imagesizes
|
||||
|
||||
author = "Mak Kolybabi <mak@kolybabi.com>"
|
||||
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
||||
categories = {"external", "safe"}
|
||||
|
||||
local render = function(params, options)
|
||||
-- Add in a marker for each GPS coordinate.
|
||||
local markers = {}
|
||||
for coords, ips in pairs(geoip.get_all_by_gps()) do
|
||||
table.insert(markers, coords)
|
||||
end
|
||||
params["markers"] = options["marker_style"] .. "|" .. table.concat(markers, "|")
|
||||
|
||||
-- Format the parameters into a properly encoded URL.
|
||||
local query = "/maps/api/staticmap?" .. url.build_query(params)
|
||||
stdnse.debug1("The query URL is: %s", query)
|
||||
|
||||
-- Check that the query string is below the 8192 character limit after
|
||||
-- URL-encoding.
|
||||
if #query > 8192 then
|
||||
return false, ("Refused to send query since URL path is %d chararacters, but Google Maps limits to 8192."):format(#query)
|
||||
end
|
||||
|
||||
local res = http.get("maps.googleapis.com", 80, query)
|
||||
if not res or res.status ~= 200 then
|
||||
return false, ("Failed to recieve map using query '%s'."):format(query)
|
||||
end
|
||||
|
||||
local f = io.open(options["map_path"], "w")
|
||||
if not f then
|
||||
return false, ("Failed to open file '%s'."):format(options["map_path"])
|
||||
end
|
||||
|
||||
if not f:write(res.body) then
|
||||
return false, ("Failed to write file '%s'."):format(options["map_path"])
|
||||
end
|
||||
|
||||
f:close()
|
||||
|
||||
return true, ("The map has been saved at '%s'."):format(options["map_path"])
|
||||
end
|
||||
|
||||
local parse_args = function()
|
||||
local options = {}
|
||||
local params = {}
|
||||
|
||||
local api_key = stdnse.get_script_args(SCRIPT_NAME .. '.api_key')
|
||||
if not api_key then
|
||||
return false, "Need to specify an API key, get one at https://developers.google.com/maps/documentation/static-maps/."
|
||||
end
|
||||
params["key"] = api_key
|
||||
|
||||
local center = stdnse.get_script_args(SCRIPT_NAME .. ".center")
|
||||
if center then
|
||||
params["center"] = center
|
||||
end
|
||||
|
||||
local format = stdnse.get_script_args(SCRIPT_NAME .. ".format")
|
||||
if format then
|
||||
params["format"] = format
|
||||
end
|
||||
|
||||
local language = stdnse.get_script_args(SCRIPT_NAME .. ".language")
|
||||
if language then
|
||||
params["language"] = language
|
||||
end
|
||||
|
||||
local layer = stdnse.get_script_args(SCRIPT_NAME .. ".layer")
|
||||
if layer then
|
||||
params["layer"] = layer
|
||||
end
|
||||
|
||||
local map_path = stdnse.get_script_args(SCRIPT_NAME .. '.map_path')
|
||||
if map_path then
|
||||
options["map_path"] = map_path
|
||||
else
|
||||
return false, "Need to specify a path for the map."
|
||||
end
|
||||
|
||||
local marker_style = stdnse.get_script_args(SCRIPT_NAME .. ".marker_style")
|
||||
stdnse.debug1('--> [%s]', marker_style)
|
||||
if not marker_style then
|
||||
marker_style = ""
|
||||
end
|
||||
options["marker_style"] = marker_style
|
||||
|
||||
local scale = stdnse.get_script_args(SCRIPT_NAME .. ".scale")
|
||||
if scale then
|
||||
params["scale"] = scale
|
||||
end
|
||||
|
||||
local size = stdnse.get_script_args(SCRIPT_NAME .. ".size")
|
||||
if not size then
|
||||
size = "640x640"
|
||||
end
|
||||
params["size"] = size
|
||||
|
||||
return true, params, options
|
||||
end
|
||||
|
||||
postrule = function()
|
||||
-- Only run if a previous script has registered geolocation data.
|
||||
return not geoip.empty()
|
||||
end
|
||||
|
||||
action = function()
|
||||
local output = stdnse.output_table()
|
||||
|
||||
-- Parse and sanity check the command line arguments.
|
||||
local status, params, options = parse_args()
|
||||
if not status then
|
||||
output.ERROR = params
|
||||
return output, output.ERROR
|
||||
end
|
||||
|
||||
-- Render the map.
|
||||
local status, msg = render(params, options)
|
||||
if not status then
|
||||
output.ERROR = msg
|
||||
return output, output.ERROR
|
||||
end
|
||||
|
||||
return output, stdnse.format_output(true, msg)
|
||||
end
|
||||
Reference in New Issue
Block a user