Hiawatha as a reverse proxy for Nessus

Nessus is a popular vulnerability scanner by Tenable Network Security. According to Tenable, it’s the most widely used of its kind worldwide. There are several license flavors available, including a free basic edition for home users. Unfortunately, Nessus requires root permissions to run correctly. This means that ironically, not unlike its namesake, the vulnerability scanner itself may be vulnerable to attack. Enter the security-aware Hiawatha webserver and its reverse proxy capabilities.

Tenable Dreamcatcher

Tenable logo © Tenable Network Security

So Nessus runs as root… (To firewall, or not to firewall?)

There are a several reasons this should raise an eyebrow. First and foremost, it violates the principle of least privilege. That is, the Nessus web interface itself doesn’t necessarily require root privileges per se, though many of its scanner functions certainly do. Thus the most convenient design choice for Tenable was to allow the entire service to run with escalated privileges full time. That may not be such a big deal if the scanner instance will be run from within a protected network, situated behind a firewall which blocks unwanted access. And herein lies the rub; firewalls can tint the results, filtering certain packets, changing others, and ultimately altering the outcome of your scans. That is, you may end up seeing false negatives in Nessus due to firewall interference. Damn.

What’s the alternative? Well, you could run Nessus without a firewall of any kind, situated on a publicly addressed host. That would give the truest scan results, sure. But now you’ve got a host out there, unprotected, which most likely contains a list of all your servers along with their vulnerabilities. Double damn. Having a Nessus scanner compromised would definitely be some bad joojoo.

Or you could run Nessus behind Hiawatha, which both runs as an unprivileged user and offers some compelling security features. In that way, you can run your scanner host without a firewall on a public network without trepidation. Have your cake and eat it too, as it were.

Preparing Nessus to be proxied

Proxying Nessus via Hiawatha is a simple undertaking, but requires a few tweaks from within the Nessus UI.

From the dropdown menu on the upper-right of the Nessus GUI, click “Settings”, then the “Advanced” tab.
Nessus admin menu
Click the blue button on the right titled “New Setting”. In the New Setting dialog, enter “xmlrpc_enable_ssl” (sans quotes) in the Name field, and “no” (also without quotes) in the Value field. When finished, click Save. This will disable the TLS requirement for admin UI connections, since we’ll only be listening on the loopback interface and Hiawatha will handle encryption for us.
Disabling SSL in Nessus
Next we’ll make Nessus bind only to the local loopback interface, so that it is not directly reachable except through Hiawatha. Click on the “listen_address” setting, and change the Value to “127.0.0.1“. Click Save.
Changing Nessus to listen only on 127.0.0.1
It will take a moment for your new settings to apply. At this point, the admin UI will no longer be directly reachable from outside of the loopback interface, so it’s important to get this right the first time.
The changes have been applied

Configuring Hiawatha

If you’re using Nessus and Hiawatha together, I’ll assume that you’re smarter than the average bear. Therefore, to keep this article brief, I’ll presume you’ve already got an SSL certificate correctly installed, your server isn’t listening for any services besides Hiawatha and SSH, that SSH is correctly configured and properly hardened, etc.

hiawatha.conf

Here’s an example Hiawatha v9.13 configuration for use as a reverse proxy for Nessus, with especially pertinent portions shown in bold.

# Hiawatha main configuration file
#

# VARIABLES
#
set LOCALHOST = 127.0.0.0/8
Set MYIPv4 = 192.0.2.42
set MyIPv6 = fde4:8dba:82e1:ffff::42

# GENERAL SETTINGS
#
ServerString = Hiawatha
ServerId = www-data
ConnectionsTotal = 4096
ConnectionsPerIP = 64
ThreadPoolSize = 128
ThreadKillRate = 8
SystemLogfile = /var/log/hiawatha/system.log
GarbageLogfile = /var/log/hiawatha/garbage.log
CacheSize = 32
CacheMaxFilesize = 512
CacheRProxyExtensions = css, eot, gif, html, htm, ico, jpg, jpeg, js, otf, png, svg, swf, ttf, txt, woff, woff2
MinTLSversion = TLS1.2
DHsize = 4096
SocketSendTimeout = 30
LogfileMask = deny LOCALHOST, deny MYIPv4, deny MyIPv6
RequestLimitMask = deny LOCALHOST, deny MYIPv4, deny MyIPv6

# BINDING SETTINGS
#
Binding {
        Port = 80
        MaxKeepAlive = 32
        TimeForRequest = 3,10
}
Binding {
        Port = 443
        MaxKeepAlive = 100
        TimeForRequest = 5,30
        TLScertFile = /etc/ssl/localcerts/scanner_example_tld.pem
        MaxRequestSize = 16000
        MaxUploadSize = 16
}
Binding {
        Port = 80
        Interface = MyIPv6
        MaxKeepAlive = 32
        TimeForRequest = 3,10
}
Binding {
        Port = 443
        Interface = MyIPv6
        MaxKeepAlive = 100
        TimeForRequest = 5,30
        TLScertFile = /etc/ssl/localcerts/scanner_example_tld.pem
        MaxRequestSize = 16000
        MaxUploadSize = 16
}

# BANNING SETTINGS
#
BanOnGarbage = 300
BanOnInvalidURL = 60
BanOnMaxPerIP = 15
BanOnMaxReqSize = 300
BanOnWrongPassword = 6:900
BanOnSQLi = 3600
KickOnBan = yes
RebanDuringBan = yes
BanlistMask = deny LOCALHOST, deny MYIPv4, deny MyIPv6

# DEFAULT WEBSITE
#
Hostname = 127.0.0.1
WebsiteRoot = /srv/www/vhosts/default
StartFile = index.html
AccessLogfile = /var/log/hiawatha/access.log
ErrorLogfile = /var/log/hiawatha/error.log

# VIRTUAL HOSTS
#
VirtualHost {
        Hostname = scanner.example.tld
        WebsiteRoot = /srv/www/vhosts/default
        StartFile = index.html
        RequireTLS = yes,31536000
        ExecuteCGI = no
        PreventXSS = yes
        PreventCSRF = yes
        PreventSQLi = yes
        CustomHeader = X-Frame-Options: DENY
        RandomHeader = 512
        ReverseProxy = .* http://127.0.0.1:8834 30 keep-alive
        LoginMessage = scanner.example.tld
        PasswordFile = digest:/srv/www/digest/scanner.digest
}

Setting up digest authentication

In order to prevent brute-force login attacks on Nessus, we can use HTTP digest authentication to wrap the Nessus login screen. Wrapping Nessus with a digest challenge isn’t strictly necessary, but is definitely recommended as part of a layered security approach. This helps in two ways:

  1. Unless the name of the server or the digest domain gives it away, an attacker will only see your Hiawatha instance and won’t otherwise have any idea that Nessus is running under the hood.
  2. Since successful authentication against Hiawatha itself is required prior to actually logging in to the Nessus admin UI, Hiawatha is able to block brute-force attacks and preemptively ban abusive users before they even get access to the potentially vulnerable Nessus UI code.

Digest authentication in Hiawatha requires at least two entries in the relevant vhost stanza of your configuration file, namely LoginMessage and PasswordFile, and a digest database containing your user credentials. Hiawatha uses standard HTTP digest format, but also comes with a handy tool called wigwam that can create one for you. For example:

wigwam -d Nessus-Airlock scanner.example.tld somepassword > /srv/www/digest/scanner.digest


In my illustration, I’ve created a user called ‘Nessus-Airlock’ for the auth domain ‘scanner.example.tld’, with a password of ‘somepassword’ (which I shouldn’t need to remind you is a terrible password). The results are piped out to a file called ‘/srv/www/digest/scanner.digest‘, which we will use as our PasswordFile target in our Hiawatha configuration (see sample config above). We should also make sure that the digest file is readable only by root and Hiawatha, so that the password list can’t be readily cracked by an unprivileged user on the system. Assuming the Hiawatha process is running as the ‘www-data’ user:

chown root:www-data /srv/www/digest/scanner.digest \
&& chmod 640 /srv/www/digest/scanner.digest

When you’re satisfied with your configuration, restart Hiawatha, e.g.:

/etc/init.d/hiawatha restart

Results

You should of course confirm that your host isn’t exposing any unnecessary services via the usual methods. That said, at this point Nessus should be situated safely behind Hiawatha. The latter will provide a worthy barrier against attacks on your host, including SQL injection, cross-site request forgeries, cross-site scripting, resource exhaustion and brute-force attacks. Incidentally, if you’ve set a reverse proxy cache as in the example configuration above, it should also be faster and more responsive to use than a vanilla Nessus installation. Win-win.

Enjoy, and let me know if you have any questions by leaving a comment below.

One thought on “Hiawatha as a reverse proxy for Nessus

  1. Hi!

    Could you please advise regarding an initial configuration of Hiawatha Reverse Proxy?
    I would be interested in some explanation of the different section in the configuration file.

    In the end I want to run Hiawatha Reverse Proxy + Let’s Encrypt certificate with SSL termination.

    THX

Leave a Reply

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