NMap XSLT for web-apps URL extraction

I’ve just wasted 2 hours of sleep, but I’ve (finally) figured out some XSLT basics and created this simple XSL template to extract base URLs of web-applications from the XML output of a NMap scan. Very handy when you want to automatically pass NMap scan results to a web-application sitemap enumeration tool, such as dirsearch or dirb.

Just save the file to nmap-http-services.xsl and run xsltproc nmap-http-services.xsl nmap.xml, given that nmap.xml is the output of your nmap -oX nmap.xml ... scan.

Now dude, go get some sleep.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="https://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="yes"/>
<xsl:template match="/nmaprun">
<xsl:for-each select="host">
<xsl:for-each select="ports/port">
<xsl:if test="state/@state = 'open' and service/@name = 'http'">
<xsl:if test="../../hostnames/hostname[@type='user']">
<xsl:if test="@portid = '80'">
<xsl:text>https://</xsl:text>
<xsl:value-of select="../../hostnames/hostname[@type='user']/@name"/>
<xsl:text>
</xsl:text>
</xsl:if>
<xsl:if test="@portid = '443'">
<xsl:text>https://</xsl:text>
<xsl:value-of select="../../hostnames/hostname[@type='user']/@name"/>
<xsl:text>
</xsl:text>
</xsl:if>
<xsl:if test="@portid != '80' and @portid != '443'">
<xsl:text>https://</xsl:text>
<xsl:value-of select="../../hostnames/hostname[@type='user']/@name"/>
<xsl:value-of select="portid"/>
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:if>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Using NMap XML output

It is widely known that NMap is the most underestimated penetration testing tool out there, so in case you don’t use its XML output to the full extent (as I did just a month ago), this post is for you.

There is a whole section in NMap help dedicated to output formats.

OUTPUT:
-oN/-oX/-oS/-oG <file>: Output scan in normal, XML, s|<rIpt kIddi3, and Grepable format, respectively, to the given filename.
-oA <basename>: Output in the three major formats at once
-v: Increase verbosity level (use -vv or more for greater effect)
-d: Increase debugging level (use -dd or more for greater effect)
--reason: Display the reason a port is in a particular state
--open: Only show open (or possibly open) ports
--packet-trace: Show all packets sent and received
--iflist: Print host interfaces and routes (for debugging)
--append-output: Append to rather than clobber specified output files
--resume <filename>: Resume an aborted scan
--stylesheet <path/URL>: XSL stylesheet to transform XML output to HTML
--webxml: Reference stylesheet from Nmap.Org for more portable XML
--no-stylesheet: Prevent associating of XSL stylesheet w/XML output

With time I got used to type -oA <basename> in order to get the reports in three formats: actual NMap output in .nmap, greppable text in .gnmap, and XML document in .xml.

Most people I know get confused when it comes to XML parsing, so the most popular use for NMap XML output is to open it in Zenmap, look at nice graphs, play around with sorting, and then close and never open it again. The first good news is that you can open multiple XML files in Zenmap by adding new files to those already open. This is handy, but you can’t save everything you’ve opened altogether to a new XML document, so this opportunity is of limited use.

Second, you can use xsltproc tool (in OS X it can be obtained by brewing libxml2) to create a nicely looking HTML report out of your NMap XML. Just type…

xsltproc report.xml > report.html

…and you’re done. Then you can open it in any browser and enjoy. You can also change the resulting HTML style by editing nmap.xsl file (brew puts it to /usr/local/share/nmap/) to add custom highlights and virtually anything you can get out of an XML.

That’s all good, but we rarely have just one NMap scan per engagement, right? And combining multiple XML files into one document is not something you can do easily. For that, you can use xml-cat tool from xml-coreutils. It simply concatenates multiple XML documents putting the <root>…</root> container around them. To use xsltproc with the result you have to replace root with nmaprun and add the following header right after the first line of the XML file for it to look like this:

<?xml version=”1.0"?>
<!DOCTYPE nmaprun>
<?xml-stylesheet href=”file:///usr/local/bin/../share/nmap/nmap.xsl” type=”text/xsl”?>
<nmaprun>
(everything between <root> and </root> does here)
</nmaprun>

After that, you can generate a pretty HTML report and review your NMap scan results sipping coffee and listening to music.

Hope this helps, stay safe, till next time!