TrueNAS Security Testing: API Key, SMB Shares, Root Access, iSCSI Credentials, and Storage Exposure

TrueNAS (formerly FreeNAS) is the most widely deployed self-hosted NAS operating system, managing petabytes of storage in home labs, small businesses, and enterprises. Its security profile centers on the fact that TrueNAS runs as root and its API provides direct access to the filesystem, user accounts, and all storage services. Key assessment areas: TrueNAS API keys created in the web UI provide full root-level system access equivalent to the root password; GET /api/v2.0/sharing/smb returns all SMB share paths and their guest access settings; GET /api/v2.0/iscsi/auth returns iSCSI CHAP authentication usernames and secrets in plaintext; GET /api/v2.0/keychaincredential returns SSH private keys stored for replication tasks; and TrueNAS allows executing shell commands via the API using the core.bulk method when authenticated as root. This guide covers systematic TrueNAS security assessment.

Table of Contents

  1. API Key and Authentication
  2. SMB, NFS, and iSCSI Share Exposure
  3. SSH Key and Credential Extraction
  4. TrueNAS Security Hardening

API Key and Authentication

# TrueNAS REST API v2.0 — API key authentication
TRUENAS_URL="https://truenas.example.com"
API_KEY="your-truenas-api-key"

# Verify API key and get system info
curl -s "${TRUENAS_URL}/api/v2.0/system/info" \
  -H "Authorization: Bearer ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Hostname: {d.get(\"hostname\")}')
print(f'TrueNAS version: {d.get(\"version\")}')
print(f'System product: {d.get(\"system_product\")}')
print(f'Uptime seconds: {d.get(\"uptime_seconds\")}')
print(f'Cores: {d.get(\"cores\")}')
" 2>/dev/null

# List all API keys — only root can see all keys
curl -s "${TRUENAS_URL}/api/v2.0/api_key" \
  -H "Authorization: Bearer ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
keys = json.load(sys.stdin)
print(f'API keys configured: {len(keys)}')
for k in keys:
    print(f'  [{k.get(\"id\")}] {k.get(\"name\")} created={k.get(\"created_at\")} user={k.get(\"username\")}')
" 2>/dev/null

# List all local users — includes shell access configuration
curl -s "${TRUENAS_URL}/api/v2.0/user" \
  -H "Authorization: Bearer ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
users = json.load(sys.stdin)
print(f'Users: {len(users)}')
for u in users:
    if not u.get('builtin'):
        print(f'  [{u.get(\"uid\")}] {u.get(\"username\")} shell={u.get(\"shell\")} sudo={u.get(\"sudo\")} email={u.get(\"email\")}')
" 2>/dev/null

SMB, NFS, and iSCSI Share Exposure

# TrueNAS storage shares — reveals all shared paths and access controls
TRUENAS_URL="https://truenas.example.com"
API_KEY="your-truenas-api-key"

# Get all SMB shares — includes guest access settings and dataset paths
curl -s "${TRUENAS_URL}/api/v2.0/sharing/smb" \
  -H "Authorization: Bearer ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
shares = json.load(sys.stdin)
print(f'SMB shares: {len(shares)}')
for s in shares:
    print(f'  {s.get(\"name\")}: {s.get(\"path\")} guest={s.get(\"guestok\")} enabled={s.get(\"enabled\")}')
    if s.get('comment'):
        print(f'    Comment: {s.get(\"comment\")}')
" 2>/dev/null

# Get all NFS shares — includes allowed hosts and network restrictions
curl -s "${TRUENAS_URL}/api/v2.0/sharing/nfs" \
  -H "Authorization: Bearer ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
shares = json.load(sys.stdin)
print(f'NFS shares: {len(shares)}')
for s in shares:
    print(f'  {s.get(\"path\")} networks={s.get(\"networks\")} hosts={s.get(\"hosts\")} ro={s.get(\"ro\")}')
" 2>/dev/null

# Get iSCSI configuration — CHAP secrets are stored in plaintext
curl -s "${TRUENAS_URL}/api/v2.0/iscsi/auth" \
  -H "Authorization: Bearer ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
auth = json.load(sys.stdin)
print(f'iSCSI auth groups: {len(auth)}')
for a in auth:
    print(f'  Tag {a.get(\"tag\")}: user={a.get(\"user\")} secret={a.get(\"secret\")} peeruser={a.get(\"peeruser\")}')
" 2>/dev/null

# Get iSCSI extents — reveals underlying disk/zvol paths
curl -s "${TRUENAS_URL}/api/v2.0/iscsi/extent" \
  -H "Authorization: Bearer ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
extents = json.load(sys.stdin)
print(f'iSCSI extents: {len(extents)}')
for e in extents:
    print(f'  {e.get(\"name\")}: {e.get(\"path\")} size={e.get(\"filesize\")} type={e.get(\"type\")}')
" 2>/dev/null

SSH Key and Credential Extraction

# TrueNAS keychain credentials — stores SSH keys for replication tasks
TRUENAS_URL="https://truenas.example.com"
API_KEY="your-truenas-api-key"

# Get all keychain credentials — contains SSH private keys
curl -s "${TRUENAS_URL}/api/v2.0/keychaincredential" \
  -H "Authorization: Bearer ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
creds = json.load(sys.stdin)
print(f'Keychain credentials: {len(creds)}')
for c in creds:
    print(f'  [{c.get(\"id\")}] {c.get(\"name\")} type={c.get(\"type\")}')
    attrs = c.get('attributes',{})
    if c.get('type') == 'SSH_KEY_PAIR':
        print(f'    Private key: {str(attrs.get(\"private_key\",\"\"))[:60]}...')
        print(f'    Public key: {str(attrs.get(\"public_key\",\"\"))[:60]}...')
    elif c.get('type') == 'SSH_CREDENTIALS':
        print(f'    Host: {attrs.get(\"host\")}:{attrs.get(\"port\")}')
        print(f'    Username: {attrs.get(\"username\")}')
" 2>/dev/null

# Get cloud credentials (S3, B2, Dropbox, etc.) used for cloud sync tasks
curl -s "${TRUENAS_URL}/api/v2.0/cloudsync/credentials" \
  -H "Authorization: Bearer ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
creds = json.load(sys.stdin)
print(f'Cloud sync credentials: {len(creds)}')
for c in creds:
    attrs = c.get('attributes',{})
    print(f'  [{c.get(\"id\")}] {c.get(\"name\")} provider={c.get(\"provider\")}')
    # AWS S3, Backblaze B2, etc.
    for key in ['access_key_id','secret_access_key','account','key','token']:
        if attrs.get(key):
            print(f'    {key}: {attrs.get(key)}')
" 2>/dev/null

TrueNAS Security Hardening

TrueNAS Security Hardening Checklist:
Security TestMethodRisk
API key root-level accessGET /api/v2.0/system/info — confirms API key gives root system access; TrueNAS API keys have full root privileges including filesystem access, user management, and service configurationCritical
SMB share guest access enumerationGET /api/v2.0/sharing/smb — returns all share names, filesystem paths, and guestok settings; shares with guestok=true accessible without credentials from the networkHigh
iSCSI CHAP credential extractionGET /api/v2.0/iscsi/auth — returns iSCSI authentication groups with CHAP username, secret, peer username, and peer secret in plaintextHigh
SSH private key extraction from keychainGET /api/v2.0/keychaincredential — returns SSH key pairs and SSH credential entries including private keys in plaintext; keys used for replication provide access to remote systemsCritical
Cloud provider credential exposureGET /api/v2.0/cloudsync/credentials — returns AWS S3 access key ID and secret, Backblaze B2 account and key, and credentials for all configured cloud sync providersHigh

Automate TrueNAS Security Testing

Ironimo tests TrueNAS deployments for API key root access scope assessment, SMB share guest access configuration, iSCSI CHAP secret extraction, SSH private key retrieval from keychain credentials, cloud sync provider credential exposure (AWS S3, Backblaze B2), user enumeration with shell access, NFS share network restriction audit, and two-factor authentication configuration.

Start free scan