Last active
May 24, 2021 22:40
-
-
Save aayla-secura/10b8cf9b779b6edec35ed135378789f5 to your computer and use it in GitHub Desktop.
Parse nmap output to print host port
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# TODO | |
# - Consolidate ports for the same host from different files | |
ONE_PER_LINE=0 | |
AS_URLS=0 | |
AS_IPS=0 | |
NO_VERSION=0 | |
SEP=" " | |
SUBSEP="," | |
FILES=() | |
HTTPS_RE="https|http.*(ssl|tls)|(ssl|tls).*http" | |
HTTP_RE="http|web" | |
HTTP_PORTS="80,8080,8000,8001" | |
HTTPS_PORTS="443,8443" | |
usage() { | |
cat <<EOF | |
Print open ports in nmap scan. | |
Usage: $(basename ${0}) [<options>] <.gnmap file> ... | |
Option: | |
-1 Display one open port per line. Default is one host per line with a comma-separated list of ports. | |
-s|--sep <sep> Separator to use between host and port. Default is '${SEP}'. | |
-S|--subsep <sep> Separator to use between ports. Default is '${SUBSEP}'. Ignored if -1 is given. | |
-u|--url Display HTTP services as URLs (this enables -1). Non-matching ports will not be displayed. | |
-n|--ip Do not use the domain name, only IP address. | |
-N|--no-version Do not show the version info. | |
--http-re <regex> Regex to use to detect HTTP services (checked last). Set to empty to disable and check only port. Default is '${HTTP_RE}'. | |
--https-re <regex> Regex to use to detect HTTPS services (checked first). Set to empty to disable and check only port. Default is '${HTTPS_RE}'. | |
--http-ports <ports> Always treat those ports (comma-separated) as HTTP services. Default is '${HTTP_PORTS}'. | |
--https-ports <ports> Always treat those ports (comma-separated) as HTTPS services. Default is '${HTTPS_PORTS}'. | |
Multiple files can be given. Comparison is case-insensitive. | |
EOF | |
exit 1 | |
} | |
while [[ $# -gt 0 ]] ; do | |
case "${1}" in | |
-1) | |
ONE_PER_LINE=1 | |
;; | |
-u|--url) | |
AS_URLS=1 | |
ONE_PER_LINE=1 | |
;; | |
-n|--ip) | |
AS_IPS=1 | |
;; | |
-N|--no-version) | |
NO_VERSION=1 | |
;; | |
-s|--sep) | |
SEP="${2}" | |
shift | |
;; | |
-S|--subsep) | |
SUBSEP="${2}" | |
shift | |
;; | |
--http-re) | |
HTTP_RE="${2}" | |
shift | |
;; | |
--https-re) | |
HTTPS_RE="${2}" | |
shift | |
;; | |
--http-ports) | |
HTTP_PORTS="${2}" | |
shift | |
;; | |
--https-ports) | |
HTTPS_PORTS="${2}" | |
shift | |
;; | |
-*) | |
usage | |
;; | |
*) | |
FILES+=("${1}") | |
;; | |
esac | |
shift | |
done | |
awk -F '\t' \ | |
-v one_per_line="${ONE_PER_LINE}" \ | |
-v as_urls="${AS_URLS}" \ | |
-v as_ips="${AS_IPS}" \ | |
-v no_version="${NO_VERSION}" \ | |
-v http_re="${HTTP_RE}" \ | |
-v https_re="${HTTPS_RE}" \ | |
-v http_ports="${HTTP_PORTS}" \ | |
-v https_ports="${HTTPS_PORTS}" \ | |
-v sep="${SEP}" \ | |
-v subsep="${SUBSEP}" ' | |
function show_host_compact(host, ports, _p, _first, _pnum, _proto, _srv) { | |
_first = 1 | |
for (_p in ports) { | |
if (! is_open(ports[_p])) { continue } | |
if (_first) { | |
printf "%s%s", hostname(host, 1), sep | |
} | |
_pnum = port_num(ports[_p]) | |
_proto = port_proto(ports[_p]) | |
_srv = port_srv(ports[_p]) | |
printf "%s%s/%s", (_first ? "" : subsep), _pnum, _proto | |
if (! no_version) { printf " (%s)", _srv } | |
_first = 0 | |
} | |
print "" | |
} | |
function show_host(host, ports, _p, _http, _pnum, _proto, _srv) { | |
for (_p in ports) { | |
if (! is_open(ports[_p])) { continue } | |
_pnum = port_num(ports[_p]) | |
_proto = port_proto(ports[_p]) | |
_srv = port_srv(ports[_p]) | |
if (as_urls) { | |
_http = http_proto(ports[_p]) | |
if (!_http) { continue } | |
printf "%s://%s:%s", _http, hostname(host), _pnum | |
} else { | |
printf "%s%s%s/%s", hostname(host, 1), sep, _pnum, _proto | |
} | |
if (! no_version) { printf " (%s)", _srv } | |
printf "\n" | |
} | |
} | |
function hostname(host, full, _f) { | |
if (full) { _f = 0 } | |
else { _f = 2 } | |
match(host, /([0-9.]+) \((.*)\)$/, m) | |
if (m[2] && ! as_ips) { return m[_f] } | |
return m[1] | |
} | |
function http_proto(port, _pnum, _srv) { | |
_pnum = port_num(port) | |
_srv = port_srv(port) | |
if (_port_or_service_matches(_srv, _pnum, https_re, https_ports)) { | |
return "https" | |
} | |
if (_port_or_service_matches(_srv, _pnum, http_re, http_ports)) { | |
return "http" | |
} | |
} | |
function _port_or_service_matches(srv, port, srv_re, port_list, _tmp, _i) { | |
if (srv_re && srv ~ srv_re) { return 1 } | |
split(port_list, _tmp, / *, */) | |
for (_i in _tmp) { | |
if (port == _tmp[_i]) { return 1 } | |
} | |
} | |
function is_open(port) { | |
return (port_field(port, 2) == "open") | |
} | |
function port_num(port) { | |
return port_field(port, 1) | |
} | |
function port_proto(port) { | |
return port_field(port, 3) | |
} | |
function port_srv(port, _srv) { | |
_srv = port_field(port, 5) " " port_field(port, 7) | |
return (_srv == " " ? "unknown" : _srv) | |
} | |
function port_field(port, i, _tmp) { | |
split(port, _tmp, "/") | |
return _tmp[i] | |
} | |
BEGIN { IGNORE_CASE = 1 } | |
# ($0, /^Ports: *(.*)/, m) { | |
($2 ~ /^Ports:/) { | |
host = gensub(/Host: /, "", 1, $1) | |
split(gensub(/Ports: /, "", 1, $2), ports, /, /) | |
if (one_per_line) { | |
show_host(host, ports) | |
} else { | |
show_host_compact(host, ports) | |
} | |
} | |
' "${FILES[@]}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment