Return to
Portfolio

77. Nessus Vulnerability Scanner

The results of a Nessus scan, saved as XML, can be collected and parsed with NXLog Enterprise Edition.

Scan Sample
<?xml version="1.0" ?>
<NessusClientData_v2>
    <Report xmlns:cm="http://www.nessus.org/cm" name="Scan Testbed">
        <ReportHost name="192.168.1.112">
            <HostProperties>
                <tag name="HOST_END">Wed Jun 18 04:20:45 2014</tag>
                <tag name="patch-summary-total-cves">1</tag>
                <tag name="traceroute-hop-1">?</tag>
                <tag name="traceroute-hop-0">10.10.10.20</tag>
                <tag name="operating-system">Linux Kernel</tag>
                <tag name="host-ip">192.168.1.112</tag>
                <tag name="HOST_START">Wed Jun 18 04:19:21 2014</tag>
            </HostProperties>
            <ReportItem port="6667" svc_name="irc" protocol="tcp" severity="0" pluginID="22964"
                        pluginName="Service Detection" pluginFamily="Service detection">
                <description>It was possible to identify the remote service by its banner or by looking at the error
                    message it sends when it receives an HTTP request.
                </description>
                <fname>find_service.nasl</fname>
                <plugin_modification_date>2014/06/03</plugin_modification_date>
                <plugin_name>Service Detection</plugin_name>
                <plugin_publication_date>2007/08/19</plugin_publication_date>
                <plugin_type>remote</plugin_type>
                <risk_factor>None</risk_factor>
                <script_version>$Revision: 1.137 $</script_version>
                <solution>n/a</solution>
                <synopsis>The remote service could be identified.</synopsis>
                <plugin_output>An IRC server seems to be running on this port is running on this port.</plugin_output>
            </ReportItem>
        </ReportHost>
    </Report>
</NessusClientData_v2>
Note
While the above sample illustrates the correct syntax, it is not a complete Nessus report. For more information refer to the Nessus v2 File Format document on tenable.com.

The preferred approach for parsing Nessus scans is with im_perl and a Perl script; this provides fine-grained control over the collected information. If Perl is not available, the xm_multiline and xm_xml extension modules can be used instead. Both methods require NXLog Enterprise Edition.

Example 346. Parsing Events With Perl

In this example, the im_perl input module executes the nessus.pl Perl script which reads the Nessus scan. The script generates an event for each ReportItem, and includes details from Report and ReportHost in each event. Furthermore, normalized $EventTime, $Severity, and $SeverityValue fields are added to the event record.

nxlog.conf [Download file]
1
2
3
4
<Input perl>
    Module      im_perl
    PerlCode    nessus.pl
</Input>
Event Sample
{
  "EventTime": "2014-06-18 04:20:45",
  "Report": "Scan Testbed",
  "ReportHost": "192.168.1.112",
  "port": "6667",
  "svc_name": "irc",
  "protocol": "tcp",
  "NessusSeverityValue": 0,
  "NessusSeverity": "INFO",
  "SeverityValue": 2,
  "Severity": "INFO",
  "pluginID": "22964",
  "pluginName": "Service Detection",
  "pluginFamily": "Service detection",
  "description": "It was possible to identify the remote service by its banner or by looking at the error\nmessage it sends when it receives an HTTP request.\n",
  "fname": "find_service.nasl",
  "plugin_modification_date": "2014/06/03",
  "plugin_name": "Service Detection",
  "plugin_publication_date": "2007/08/19",
  "plugin_type": "remote",
  "risk_factor": "None",
  "script_version": "$Revision: 1.137 $",
  "solution": "n/a",
  "synopsis": "The remote service could be identified.",
  "plugin_output": "An IRC server seems to be running on this port is running on this port.",
  "EventReceivedTime": "2017-11-29 20:29:40",
  "SourceModuleName": "perl",
  "SourceModuleType": "im_perl"
}
nessus.pl [Download file]
#!/usr/bin/perl

use strict;
use warnings;

use FindBin;
use lib $FindBin::Bin;
use Log::Nxlog;
use XML::LibXML;

sub read_data {
    my $doc = XML::LibXML->load_xml( location => 'scan.nessus' );
    my $report = $doc->findnodes('/NessusClientData_v2/Report');
    my @nessus_sev = ("INFO","LOW","MEDIUM","HIGH","CRITICAL");
    my @nxlog_sev_val = (2,3,4,5,5);
    my @nxlog_sev = ("INFO","WARNING","ERROR","CRITICAL","CRITICAL");
    my %mon2num = qw(
                      Jan 01  Feb 02  Mar 03  Apr 04 May 05 Jun 06
                      Jul 07  Aug 08  Sep 09  Oct 10 Nov 11 Dec 12
                     );
    my $eventtime;

    foreach my $reportHost ( $doc->findnodes('/NessusClientData_v2/Report/ReportHost') )
    {
        $eventtime = "";
        foreach my $properties ( $reportHost->findnodes('./HostProperties/tag') ) {
            if ($properties->getAttribute('name') eq "HOST_END") {
                my($dow, $m, $d, $t, $y) = $properties->textContent =~
                  m<^([a-zA-Z]+) ([a-zA-Z]+) (\d+) (\d+:\d+:\d+) (\d+)$> or die "Not a valid date";
               $eventtime= $y . "-" . $mon2num{$m} . "-" . $d . " " . $t;
            }
         }
        foreach my $reportItem ( $reportHost->findnodes('./ReportItem') ) {
            my $event = Log::Nxlog::logdata_new();
            my $raw_event = $reportItem->toString();
            Log::Nxlog::set_field_string( $event, 'raw_event', $raw_event );
            Log::Nxlog::set_field_string( $event, 'EventTime', $eventtime );
            Log::Nxlog::set_field_string( $event, 'Report', $report->get_node(1)->getAttribute('name') );
            Log::Nxlog::set_field_string( $event, 'ReportHost', $reportHost->getAttribute('name') );
            my @atts = $reportItem->getAttributes();
            foreach my $at (@atts) {
                my $na = $at->getName();
                my $va = "" . $at->getValue();
                if ($na eq "severity") {
                    my $severity = $va + 0;
                    Log::Nxlog::set_field_integer( $event, "NessusSeverityValue", $severity );
                    Log::Nxlog::set_field_string( $event, "NessusSeverity", $nessus_sev[$severity] );
                    Log::Nxlog::set_field_integer( $event, "SeverityValue", $nxlog_sev_val[$severity] );
                    Log::Nxlog::set_field_string( $event, "Severity", $nxlog_sev[$severity] );
                } else {
                    Log::Nxlog::set_field_string( $event, $na, $va );
                }
            }
            if ( $reportItem->hasChildNodes ) {
                my @kids = grep { $_->nodeType == XML_ELEMENT_NODE }
                  $reportItem->childNodes();
                foreach my $kid (@kids) {
                    my $na = $kid->getName();
                    my $va = "" . $reportItem->getChildrenByTagName($na);
                    Log::Nxlog::set_field_string( $event, $na, $va );
                }
            }
            Log::Nxlog::add_input_data($event);
        }
    }
}
Example 347. Parsing Events With xm_multiline

This example depicts an alternative way to collect results from Nessus XML scan files, recommended only if Perl is not available. This configuration generates an event for each ReportItem found in the scan report.

nxlog.conf [Download file]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<Extension multiline_parser>
    Module          xm_multiline
    HeaderLine      /^<ReportItem/
    EndLine         /^<\/ReportItem>/
</Extension>

<Extension _xml>
    Module          xm_xml
    ParseAttributes TRUE
</Extension>

<Input in>
    Module          im_file
    File            "nessus_report.xml"
    InputType       multiline_parser
    <Exec>
        # Discard everything that doesn't seem to be an xml event
        if $raw_event !~ /^<ReportItem/ drop();

        # Parse the xml event
        parse_xml();
    </Exec>
</Input>
Event Sample
{
  "EventReceivedTime": "2017-11-09 10:22:58",
  "SourceModuleName": "in",
  "SourceModuleType": "im_file",
  "ReportItem.port": "6667",
  "ReportItem.svc_name": "irc",
  "ReportItem.protocol": "tcp",
  "ReportItem.severity": "0",
  "ReportItem.pluginID": "22964",
  "ReportItem.pluginName": "Service Detection",
  "ReportItem.pluginFamily": "Service detection",
  "ReportItem.description": "It was possible to identify the remote service by its banner or by looking at the error\nmessage it sends when it receives an HTTP request.\n",
  "ReportItem.fname": "find_service.nasl",
  "ReportItem.plugin_modification_date": "2014/06/03",
  "ReportItem.plugin_name": "Service Detection",
  "ReportItem.plugin_publication_date": "2007/08/19",
  "ReportItem.plugin_type": "remote",
  "ReportItem.risk_factor": "None",
  "ReportItem.script_version": "$Revision: 1.137 $",
  "ReportItem.solution": "n/a",
  "ReportItem.synopsis": "The remote service could be identified.",
  "ReportItem.plugin_output": "An IRC server seems to be running on this port is running on this port."
}