-
Notifications
You must be signed in to change notification settings - Fork 55
Usage
Export nmap scan results using -oX
option in nmap:
nmap -A -T4 -oX nmap.xml [target]
Choose format (html, csv, markdown or json) and use with nmap formatter
nmap-formatter [html|csv|md|json|dot|sqlite|excel|d2] [path-to-nmap.xml] [flags]
Or alternatively you can read file from stdin and parse it
cat some.xml | nmap-formatter json
Same way it can be piped using nmap -> nmap-formatter -> jq. But I would suggest to save XML output to some file in the first place.
nmap -v -A -T5 -oX - 192.168.1.1 | nmap-formatter json | jq
Convert nmap output to nicer HTML
nmap-formatter html [path-to-nmap.xml] > some-file.html
Convert nmap output to Markdown
nmap-formatter md [path-to-nmap.xml] > some-markdown.md
Convert nmap output to JSON
nmap-formatter json [path-to-nmap.xml]
# This approach is also possible
cat nmap.xml | nmap-formatter json
It can be also combined with a jq tool
cat nmap.xml | nmap-formatter json | jq
There is an option for filters in nmap-formatter, example of such command:
cat nmap.xml | nmap-formatter json --filter ".Status.State == 'up' && any(.Port, { .PortID == 22})" | jq
Would return only those hosts, that are not offline (state is up) and which have any .Port
(this is a list) of 22
.
List all the found ports and count them:
nmap-formatter json nmap.xml | jq -r '.Host[]?.Port[]?.PortID' | sort | uniq -c
Output:
1 "22"
2 "80"
1 "8080"
Select only those hosts that have http service running:
nmap-formatter json nmap.xml | jq '.Host[]? | . as $host | .Port[]? | select(.Service.Name== "http") | $host.HostAddress.Address' | uniq -c
Explanation:
nmap-formatter json nmap.xml | # Simply parsing nmap.xml file and converting that to json
jq '.Host[]? | # Piping through jq and making query: selecting each host. '?' showing that .Host[] array might be empty
. as $host | # Saving $host as a variable, we would use it later
.Port[]? | # Select a list of ports (which might not exist/be empty)
select(.Service.Name== "http") | # Where service name is "http", nmap determines that by itself
$host.HostAddress.Address' | # Select parent $host variable and print an address, also it's end of jq query with `'`
uniq -c # Display those addresses in unique manner, counting repeated occurences
Result of such command:
1 "192.168.1.1"
1 "192.168.1.2"
2 "192.168.1.3"
# In this case 192.168.1.3 has 2 http services running (for example on ports 80 and 8080).
Another example where it is needed to display only filtered ports:
nmap-formatter json nmap.xml | jq '.Host[]?.Port[]? | select(.State.State == "filtered") | .PortID'
Display host IP addresses that have filtered ports:
nmap-formatter json nmap.xml | jq '.Host[]? | . as $host | .Port[]? | select(.State.State == "filtered") | .PortID | $host.HostAddress.Address'
Scan just found http services with Nikto web-server scanner:
nmap-formatter json nmap.xml | jq -r '.Host[]? | . as $host | .Port[]? | . as $port | select(.Service.Name== "http") | [$host.HostAddress.Address, $port.PortID] | @tsv' | awk '{ print "-host "$1" -port "$2 }' | xargs -n4 nikto
# We extract address and port with the help of jq tool, print them separately with \t
# Like this: 192.168.1.1 80, and using awk we print arguments for `nikto` web-server scanner
# We use then xargs to pass those arguments to nikto itself
NB! In some cases it's definitely easier to use Grepable Output (nmap option -oG
) instead of this approach, this one has been made simply as a proof of concept.
There is various flags and output options that allow you to customize your output.
-
-f
,--file [filename]
outputs result to the file (by default output goes to stdout) -
--help
display help message -
--version
display version (also can be used: ./nmap-formatter version)
Custom options can be used to deliver some information to the output (like user ID, or environment or hostname where scan has been performed). For this purpose there is --x-opts
flag exists. It's possible to use multiple variables:
nmap-formatter md nmap-file.xml --x-opts="Hostname=$HOST" --x-opts="Terminal=$TERM"
The end result would contain those values after Scan Summary
chapter. It would look something like this:
Key | Value |
---|---|
Hostname | hostname123 |
Terminal | xterm-256color |
This command is applicable only in HTML & Markdown templates.
Common options that are applied for all formats/files
Flag | Description | Default | Example |
---|---|---|---|
--filter |
Filter each host by using query expression language https://expr-lang.org/ which is applied to Host struct |
[] |
--filter '.Status.State == "up" && any(.Port, { .PortID in [80,443] })' or can be added multiple options (would be applied with AND rule) |
--skip-down-hosts |
Adds new filter in front of all other filter that removes hosts that are offline | false |
--skip-down-hosts=true |
Flag | Description | Default | Example |
---|---|---|---|
--html-skip-header |
Skips header (title) in HTML output | false |
--html-skip-header=true |
--html-skip-toc |
Skips table of contents in HTML output | false |
--html-skip-toc=true |
--html-skip-summary |
Skip summary, it won't show various meta information about the scan | false |
--html-skip-summary=false |
--html-skip-traceroute |
Skip traceroute information (from the machine that ran nmap to the target) | false |
--html-skip-traceroute=false |
--html-skip-metrics |
Skip miscellaneous metrics information | false |
--html-skip-metrics=true |
--html-skip-port-scripts |
Skip port scripts output (nse-scripts) | false |
--html-skip-port-scripts=false |
--html-use-template |
Use specific HTML template instead of default one | "" |
--html-use-template /path/to/template.html |
--html-dark-mode |
Dark mode in HTML template, enabled by default | true |
--html-dark-mode=false |
Flag | Description | Default | Example |
---|---|---|---|
--md-skip-header |
Skips header (title) in Markdown | false |
--md-skip-header=true |
--md-skip-toc |
Skips table of contents in Markdown | false |
--md-skip-toc=true |
--md-skip-summary |
Skip summary, it won't show various meta information about the scan | false |
--md-skip-summary=false |
--md-skip-traceroute |
Skip traceroute information (from the machine that ran nmap to the target) | false |
--md-skip-traceroute=false |
--md-skip-metrics |
Skip miscellaneous metrics information | false |
--md-skip-metrics=true |
--md-skip-port-scripts |
Skip port scripts output (nse-scripts) | false |
--md-skip-port-scripts=false |
--md-use-template |
Use specific Markdown template instead of default one | "" |
--md-use-template /path/to/template.md |
N/A
Flag | Description | Default | Example |
---|---|---|---|
--json-pretty |
Pretty print of JSON output | false |
--json-pretty=true |
N/A
Flag | Description | Default | Example |
---|---|---|---|
--sqlite-dsn |
A location to SQLite database (DSN) | nmap.sqlite |
file:nmap.db?shared=true |
--scan-id |
A unique scan ID that would allow you to populate scan table with unique identifiers | uniquely generated UUID | my-scan |
N/A