tl;dr: With the tool nmap-parse-output you can convert, manipulate or extract data from a Nmap/masscan scan output. This allows you to get the information you’re looking for by just entering a straightforward command.

Preamble

A while ago, we had to scan a mass amount of IPs within a project for a customer. While it’s feasible to read the whole output of a Nmap scan if you have just a few alive hosts, this was not possible anymore for this mass amount of systems. We’ve started with a masscan to scan all 2^16 ports of the IP ranges and wanted to perform a more precise analysis of the alive hosts (which had responded to at least one SYN packet) with Nmap. The result of this scan grew to nearly a hundred megabyte and we now had to do an analysis of which ports we had to look deeper into and which are intended to be open.

In the past, I have used the Grepable Output (-oG) sometimes, and sometimes XML Output (-oX)

with XPath extract specific information (like HTTP ports) from a scan. I never liked using sed , cut and co. very much to extract information. Mostly, because it led to unreadable lines of shell commands which are not well adaptable for other use cases.

So I’ve created a bunch of XPath queries to gather the information I’m interested. As a text file full of XPath queries is not very cool, I put them into a little tool: The result is a small shell script named nmap-parse-output. The script takes the XML output of a Nmap or masscan scan and executes an XSL Transformation file with xsltproc and prints the result.

Usage of nmap-parse-output

The usage of nmap-parse-output is pretty simple: It takes the Nmap XML output as the first argument and the command as the second argument. The list of available commands is printed if no command is given or you can look here for it. Bash and ZSH completion is support, too.

Examples

If you want to get a few impressions of what you can do with the script, here are some example commands.

Print usage and list of commands:

$ ./nmap-parse-output

Write HTML output to scan.html:

$ ./nmap-parse-output scan.xml html > scan.html

Generates a list of all HTTP(s) ports:

$ ./nmap-parse-output scan.xml http-ports http://192.168.0.1:8081 https://192.168.0.1:8443

List all names of detected services and get a list of hosts with the port for the service http-proxy:

$ ./nmap-parse-output scan.xml service-names http https http-proxy ms-wbt-server smtp $ ./nmap-parse-output scan.xml service http-proxy 192.168.0.24:8085 192.168.0.25:9000

Exclude some hosts from a scan and generate a list of ports:

$ ./nmap-parse-output scan.xml exclude '192.168.1.1,192.168.1.20' | nmap-parse-output - ports 22,80,443,8080

Filter scan-all.xml to include only hosts scanned in scan-subnet.xml and write the output to filtered-scan.xml :

$ ./nmap-parse-output scan-all.xml include $(./nmap-parse-output.sh scan-subnet.xml hosts | tr "

" ",") > filtered-scan.xml

Add comments to a scan, mark specific ports red, and generate a HTML report with the annotations:

$ ./nmap-parse-output scan.xml comment-ports '8080,10.0.20.4:443' 'this port should be filtered' | ./nmap-parse-output - mark-ports '8080,10.0.20.4:443' red | ./nmap-parse-output - comment-hosts '10.0.20.1' 'look further into this host' | ./nmap-parse-output - html > test.html

Remove all ports found in scan-before.xml from scan-after.xml and write the output to filtered-scan.xml

$ ./nmap-parse-output scan-after.xml exclude-ports $(./nmap-parse-output.sh scan-before.xml host-ports | tr "

" ",") > filtered-scan.xml

Extend & Contribute

You can add new commands by creating a new XSLT file in nmap-parse-output-xslt/. Take a look at the project’s readme for more documentation.

If you created a cool new command, feel free to make a pull request! I am looking forward to your contribution! 😉