.audit-based Compliance Management in Nessus

In this post I will briefly describe how Nessus .audit-based Compliance Management works, why I like it, what could be improved and why I suppose Tenable won’t do it soon. 😉

Nessus compliance checks are mainly presented in a form of special .audit scripts. This scripting language is very different from familiar NASL (Nessus Attack Scripting Language).

Basically, it is a collection of universal checks for various objects (e.g. existence of the line or parameter in the file, access permissions of the file,  service status, etc.). Of course, nowadays Сompliance Management is not only about Operating System and software (mis)configuration. We have different network devices, databases, cloud services, etc. but originally it was the main case.

By combining the universal checks  any requirement of low-level configuration standard (CIS, DISA, etc.) can be implemented. The similar principles are used in OVAL/SCAP content.

.audit scripts

Not so long time ago, when you needed to perform a compliance scan in Nessus,  it was necessary to download .audit script from Tenable Support Portal and upload it to the scanner.

Now all security standards are available in Nessus web interface. I listed all types of systems, for which Compliance Management is supported, in post “Tenable Nessus: registration, installation, scanning and reporting“. Tenable adds new standards regularly.

However, you still can download the script from the site and upload it to Nessus:

This is very useful if you want to make your own compliance .audit file based on some existing standard, for example CIS or DISA.

Structure of the .audit script

What structure .audit file has? Here is an example for CentOS 7 CIS standard:

        <condition type:"AND">
            system      : "Linux"
            type        : FILE_CONTENT_CHECK
            description : "CentOS Linux 7 is installed"
            file        : "/etc/redhat-release"
            regex       : "^[\\s]*CentOS Linux release 7"
            expect      : "^[\\s]*CentOS Linux release 7.*"

         [ Custom Items for different CIS CentOS 7 controls ]

            <report type:"FAILED">
            description : "CentOS Linux 7 Server is not installed"
            info        : "The target system is not running CentOS Linux 7 Server"
            see_also    : "https://benchmarks.cisecurity.org/tools2/linux/CIS_CentOS_Linux_7_Benchmark_v2.1.0.pdf"

Using simple regular expressions we can check if the system we scan is really CentOS 7. If it is not, return “FAILED” status.

Here is an example of a custom_item for standard control. We are checking that there is no “+” in the beginning of the line /etc/shadow:

      system      : "Linux"
      type        : FILE_CONTENT_CHECK_NOT
      description : "..."
      info        : "..."
      reference   : "..."
      see_also    : "..."
      solution    : "..."
      file        : "/etc/shadow"
      regex       : "^[\\s]*\\+:"
      expect      : "^[\\s]*\\+:"

From the target host

And how the scanning process looks for the target host?

Let’s scan CentOS host and see it. I have created “CentOS Audit” police, scanning via ssh, getting root proviliges with sudo.

Compliance standards:

  • CIS_CentOS_7_Server_L1_v2.1.0.audit
  • CIS_CentOS_7_Server_L2_v2.1.0.audit

Content of redhat-release file will match “^[\\s]*CentOS Linux release 7”:

$ cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)

During the compliance scan Nessus connects to the target host via ssh, authenticate there, and perform some shell commands.

If you want to check the file content in Linux, you can download the whole file and then parse it in scanner or parse it with grep on the host. Right? What in fact Nessus do you can see in target host bash history. Bash script for getting shadow file content:

$ sudo -u root -p Password: sh -c 'echo nessus_su_`echo 661346525` ; LANG=C; cat '\''/etc/shadow'\''|cat; echo nessus_su_`echo 646548083`' || echo nessus_su_`echo 1013105443`
$ stty raw -echo

[/etc/shadow content]

sudo parameter “-u” specifies the user (root); “-p” specifies how shell with asks the password (“Password:”), it makes automation much easier. The “nessus_su_” lines above and below the actual output are required for accurate parsing.

Compliance scan results

Full Vulnerability and Compliance scanning of one host takes ~ 7 minutes.

For each control you can see the output of the check with a link to the high-level standards, such as NIST SP 800-171, NIST SP 800-53, CSF, ITSG, PCI-DSS


What I really like in Nessus compliance feature is a great flexibility. There is no a big difference between .audit scripts made by user and the scripts available out-of-the-box. Nessus provides a set of universal checks, that you can use in your own .audit scripts, and ready-made scripts for the most popular standards. You can use this ready-made script as is, you can express your own standards based on existing scripts or even use this scripts only as an example and create something very unique. It’s all up to you. Nesus engine will process all this .audit content in the same way.

I think that the development of custom .audit scripts could be even outsourced to the third-party. I don’t know if there is a market and a high demand for this, but it’s for sure is technically possible.

Unlike the NASL, for which there is almost no up to date documentation, for .audit you can easily get detailed description of any check. There is no a convenient way to debug the scripts, but it’s still possible.


  1. Nessus high flexibility may be a disadvantage. Some people don’t want to deal with scripts, especially for changing correct values of the parameters. It’s possible to redefine some parameters in Web GUI, but only for some small amount of controls.
  2. As you see on a screen shot, there are only 3 statuses of the control available: Failed, Warning, Passed. What if the control is not applicable?
  3. Sorting feature in web GUI is very primitive and doesn’t work properly for control numbers:
  4. Control numbers in Nessus and in “paper” CIS standard be different. For every complex CIS control, where you need to perform several checks, Nessus creates several simple “child-controls” with only one check. And they don’t have a connection with “parent-control”, all control checks are separate and you can see them in a flat list. It may be hard to understand what items of “paper” CIS standard are not compliant just by looking at the Nessus compliance report.
  5. In most cases Nessus doesn’t check that the system was configured safely, but that the system was configured literally how it is described in CIS standard. The only way to get all green statuses is to perform all recommendations of the standard as is, including the  naming of the configuration files. Otherwise you can get a non-compliant control status with the error like: ‘The file "/etc/modprobe.d/CIS.conf" could not be found
  6. Nessus don’t provide detailed messages describing configuration errors. It is not always clear what you need to fix and how to do it. Often you will see in the output that contents of some file doesn’t match some long complex regular expression. You will need to go to the system and figure out the problem manually.
  7. For correct compliance scanning you will need root permissions. But if privilege escalation on the system won’t work during the scanning, for example, root account password was changed or expired, you will not see error messages about this. You will see only problems with accessing some files.
  8. The ability to perform any shell command or even script on remote host is very flexible, but for obvious reasons, it is may be dangerous. Example of CMD_EXEC check:
    type        : CMD_EXEC
    cmd         : "/usr/bin/mount | /usr/bin/grep 'on /var/tmp '"
    expect      : "[\\s]*[,]?nosuid"

    Some attacker can also upload and execute malicious script on remote host, if he will get an access to your Nessus server. Example of such Nessus .audit script you can find in article “ZeroNights16: Enterprise Vulnerability Management“.

The most vendors of Compliance Management products seem to have a false belief, that their users can easily obtain root credentials for scanning. In fact, every IT department will be actively against it. Do you need root access for strange third-party program to perform various commands on the server? That’s doesn’t seem right. IMHO, it is still a big question how to solve this conflict efficiently.

Almost all security vendors don’t describe in their scan report why non-compliance status of some security control is actually bad. It would be great if someone will create an offensive manuals associated with CIS standards, demonstrating how misconfiguration can be practically exploited. Because Compliance Management, as it is now, it is mostly a very formal process.

In conclusion

Compliance is a very specific business driver. Organizations usually don’t do it because it’s cool or raises their’s security level. In fact, they just trying to comply some requirement with minimal efforts.

Not surprisingly, Nessus .audit scripts for Compliance Management are made in a similar manner. Sometimes they are very straightforward and not user-friendly, but in most cases it’s enough to solve the main task. In the other hand, because of this, Tenable can quickly create, update and certify the scripts when a new version of standard appears. In most cases latency is not bigger than a week.

Why don’t I think Nessus Compliance Management disadvantages won’t be fixed soon? I think, Tenable consider Nessus mainly as an external scanner for SecurityCenter. From this perspective, any limitations of Nessus web-gui are not so much important. Users of SecurityCenter, that are the most critical for Tenable, already have advanced instruments for reporting, searching for events and dashboarding.

2 thoughts on “.audit-based Compliance Management in Nessus

  1. Pingback: Tenable Nessus: registration, installation, scanning and reporting | Alexander V. Leonov

  2. Emma

    Great post Alex. Some thing close to what I am struggling to learn.
    I am having a hard time understanding how the regex lines on a .audit file works.
    for Example:
    How can I test the following (partial) entry from an audit file for RHEL 7

    regex : “^[\\s]*TimedLoginEnable[\\s]*=[\\s]*false”
    expect : “^[\\s]*TimedLoginEnable[\\s]*=[\\s]*false”


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.