On Tenable Network Security’s Nessus Discussions Forum, user Steve Chan asks whether it is possible to use the XMLRPC interface of Nessus 4.2 to display the differences between a scan report and another one, used as a comparison baseline.
As you can see you’d need to keep track of the report UUIDs (unique identifiers to distinguish between each report) and if you are scanning multiple sites, you’d need to keep track of which UUID corresponds to which site and what is the baseline etc. This usually means some kind of a database.
To spare myself the hassle of maintaining yet another piece of software and yet more code to talk to a database, I opted for another option. I generate my own UUIDs but instead of random numbers and letters I use the site’s name and current date (up to the usec) as the readableName (the human-readable name you can associate with each scan you submit to Nessus 4.2).
Since the release of Nessus 4.2, a new report file format -dubbed v2 or .nessus v2- has been pushed forward. Quoting Tenable Network Security:
‘An updated .nessus file format (.nessus v2) is now available, which allows for easier parsing of report data Descriptions can now be split into different labels such as CVSS base scores, risk factors and more. A “HostProperties” section contains information about each host which can be extracted easily (MAC addresses, operating system, etc.)’
While maintaining the XML encoding of the old .nessus v1 format, the new .nessus v2 format is, as Tenable Network Security wrote, easier to parse. But enough talking and let’s delve a bit into this new format, shall we?
What Does It Look Like?
A picture is worth a thousand words, right? ;-)
If you were accustomed to the .nessus v1 format, one of the first things you would notice is that the root node is now NessusClientData_v2 instead of NessusClientData. Moreover, each scanned host (ReportHost node) has now a nice HostProperties subnode.
HostProperties provide a set of subnodes all named tag but which have different attributes. The following tag nodes are always present:
tag name="HOST_END": time at which the scan has finished
tag name="HOST_START": time at which the scan has started
The following tag nodes are not always present as they depend on whether or not Nessus is able to discover some extra information about the host:
tag name="operating-system"
tag name="mac-address"
tag name="host-ip"
tag name="host-fqdn"
tag name="netbios-name"
Vulnerabilities, Defined
Often, I use Nessus to detect remotely-exploitable vulnerabilities only (as I consider that once an attacker has a foothold on a system, it’s game over for the defender no matter what privileges the attacker had at the beginning). In this particular case, the ReportItem node has 7 attributes:
port: TCP/IP port on which the vulnerability was detected
svc_name: service name
protocol: do I really need to explain this one?
severity: a value ranging from 1 (low) to 3 (high) evaluating how critical the vulnerability is
pluginID: Nessus plugin identifier
pluginName: human-readable name of the plugin
pluginFamily: family to which the plugin belongs to.
see_also: contains a URL for further reference. There might be zero or more of such elements
plugin_output: if present, this element provides the output of the plugin
plugin_version: plugin revision information. This can be useful when you need to check whether you have the latest version or not
bid: provides the Bugtraq ID. There might be zero or more of such elements
cve: provides CVE data. There might be zero or more of such elements
xfref: provides pointers to other vulnerability databases such as OSVDB
plugin_publication_date: well, I guess you can see what it may contain. Not always present
vuln_publication_date: same here ;-) and not always present too.
Important Note
As Renaud Deraison pointed out, the list of subnodes under ReportItem is meant to be “open”. Tenable Network Security can and will add new fields to it from time to time. So if you are writing a .nessus v2 format parser, it must ignore unhandled nodes instead of raising errors.
Well…
… I think this is pretty much what you need to know about the Nessus v2 report file format. If you spot any mistake or any missing important piece of information, please let me know by commenting on this blog entry.
Until, then I wish you some happy parsing and fiddling with XPath ;-)
—> Edited on 2010/03/02 to Add: Note about the list of ReportItem subnodes being “open” + remove XML tag “<” and “>” in the ReportItem example and the tag subnodes because they are not displayed correctly by Google Reader.
As I wrote in Automating scans on Nessus 4.2, scan automation on Nessus 4.2 is done over HTTPS using the XMLRPC interface introduced by this new major release of the popular vulnerability scanner. You do this by submitting POST requests to the scanner.
The first step toward automation is to obtain a login token (think cookie). There are many ways to do so. You can use wget for instance:
Given the login token, you can submit further POST requests for launching scans, downloading reports and making different sorts of interaction with your scanner. However, a login token, pretty much like a cookie, expires. And if someone/something logs to the scanner with the same user/password in the time between when your scripts obtained the token and when they started using it, your login token is no longer valid.
There is also the problem of sharing a freshly obtained login token between different scripts that may run in parallel: a script for submitting a scan, another for downloading reports, yet another one for deleting older reports etc.
One way of solving this issue is to use a method/subroutine that is called by your scripts whenever they need to use or grab a login token and a local file to store such token. I implemented one using the following flow chart:
To check the validity of the token (the Is valid? part of the flow chart), you can do a simple POST operation such as listing the reports or the scan policies and checking whether the status of the reply is OK. If that’s not the case, this means the token is no longer valid.
You need also to make sure that you implement strong permissions on the file that will contain the token and if you need to write to it, you need to use an exclusive lock to avoid any concurrency troubles.
There are certainly other ways for doing this but this the way I implemented on my side and it pretty much works!
With the release of Nessus 4.2, the nessus command-line client has been deprecated. Even if it still distributed with the new release, there is no new functionality introduced to it. Moreover, it is only able to generate Nessus v1 format reports and not the new Nessus v2 reports that are far easier to parse and better organized.
Automating scans with Nessus 4.2 can be performed by leveraging the new XMLRPC interface. All you need is something to generate HTTP POST requests with the right parameters and something to parse the XML responses you get back.
As of this writing, official Nessus documentation to do so is not available yet. However, a few mail exchanges with Renaud Deraison, Chief Research Officer at Tenable Security Inc. got me started and he provided very useful tips that I’d like to share with you in case you need to automate scans as I do.
To issue requests, you need to submit a login token (which you can think of as a cookie) to the Nessus scanner to prove your identity. So the first you need to do is to login to the scanner and retrieve a login token.
But first let me define a base URL that I am going to use throughout in this post: https://my.nessus.scanner:8834. Replace my.nessus.scanner with the FQDN of your Nesssus scanner, its IP address or even localhost if you are interacting with it on the same box that it is installed on.
Nessus uses a self-signed certificate so you’d need to make provisions in your programs/scripts for this. Also, please note that we are using the same TCP port that you’d use with a traditional browser.
When you issue a login request, Nessus will reply with a login token. You can think of this token as a cookie. This is all you need to authenticate to Nessus from now on. A login token looks like: 81d64733f78b6a6d34217bfedff12b3244ec20d015d26a0a
The policy_id parameter is the scan policy identifier. Obviously, you will need to use your browser to create a scan policy first so that you can have this ID. The scan_name is a human-friendly name for your scan. This is the same thing when you launch a scan using the Web UI. Please note that Nessus uses a unique scan identifier (uuid) that looks like this: 60c6eaa3-5063-0a70-bf33-c00b71d4cfaf97af24f344d0bfa1
To download or delete a scan report, you will need this uuid.
If a scan is completed (i.e. a scan report is ready), its status subnode in the XML response you receive back (each scan/report has a corresponding report node) is shown as completed.
This should be enough to get you started. In upcoming posts, I will give more detailed examples and some code snippets that might prove useful.
Big thanks to Renaud for providing some precious help!
EDITED TO ADD (2010.03.31): Apparently, you need to use a non administrator account to be able to interact with Nessus 4.2 the way I describe it as Chris Counselman pointed out in the comments below. Thanks Chris!