From Password Spray to SAML: Securing Cisco FTD AnyConnect VPN with Entra ID

 Written with the help of Claude AI

Why we did this

Random Active Directory lockouts turned out to be a large password spray against our Cisco AnyConnect VPN, and the fix was moving VPN authentication to SAML with Microsoft Entra ID.

The starting point was common: a Cisco Firepower 1100-series firewall running FTD, managed on-box, with AnyConnect users signing in with their Windows AD password. Users kept getting locked out for no obvious reason.

This post walks through what we found and every step it took to fix it, including the problems we hit along the way. It's written for small IT teams who run a similar setup and are seeing the same symptoms.

What you'll end up with:

  • VPN sign-in through Entra ID, with MFA on every connection
  • The firewall never sees or forwards AD passwords, so spray attempts can't lock AD accounts
  • Optional single sign-on through the user's default browser

Starting environment: FTD 7.2.x managed by Firepower Device Manager (FDM), AnyConnect 4.10, hybrid AD synced to Entra ID, no Entra ID P1 licences, and endpoint security plus a DLP agent on domain laptops.

Step 1: Prove the VPN is the source

One command on the FTD settled it. Before touching anything, confirm where the failed logons come from.

> show aaa-server

It doesn't depend on logging being set up, and it shows request, accept and reject counts per authentication server. Ours showed this for the AD server group:

Counter

Value

Authentication requests

~774,000

Accepts

~400

Rejects

~770,000

Nearly every attempt failed, and each failure counted as a bad password against an AD account. The LOCAL group also showed ~73,000 rejects and zero accepts. Those were attempts against the built-in default connection profiles, which authenticate against an empty local database and never reach AD.

Two surprises came out of this:

  • We weren't using RADIUS at all. The server group was plain LDAP on port 389, pointing straight at a domain controller. Check your actual config rather than relying on documentation or memory.
  • The syslog buffer was missing everything. show logging | include 113005 returned nothing despite hundreds of thousands of failures. Buffer logging was off or set below informational. If you need source IPs, enable the internal buffer at level 6 or send syslog to a server.

If the reject count is low, the VPN isn't your problem. Check event 4740 on the PDC emulator instead: the Caller Computer Name points to the real source, which could be an Exchange server, a stale credential on a phone, or a cloud sign-in through Pass-through Authentication.

Why adding MFA through NPS wouldn't have helped

The usual advice is the NPS extension for Entra MFA. That checks the AD password first and only then prompts for MFA. Every wrong guess still counts against AD, so accounts keep locking. MFA through NPS stops a guessed password from being used, but it doesn't stop the lockouts.

Also check the accepts. At this volume, a few weak passwords may have been guessed, so review active sessions with show vpn-sessiondb anyconnect for unfamiliar IPs or users before going further.

Step 2: Choose SAML, and check what manages your firewall

SAML with Entra ID was the only option that stopped the lockouts. With SAML, the firewall redirects the user to Microsoft's sign-in page and never handles the password. Entra checks it instead, and its Smart Lockout absorbs the spray. If Entra Connect uses Password Hash Sync, failed attempts never reach your domain controllers at all.

FDM or FMC?

We lost time following FMC instructions on a box managed by FDM. The two have different menus and different field names. A quick way to tell: FMC is a separate server or VM you log into, while FDM is the web UI served by the firewall itself. Most Firepower 1000-series boxes in small offices use FDM.

The FDM 7.2 certificate limitation

On FDM 7.2 and earlier, Cisco only supports Duo as a SAML identity provider. The IdP signing certificate must have Basic Constraints: CA:TRUE, and Entra's signing certificate doesn't. The symptom is the error "Failed to generate SAML AuthnRequest", and show saml metadata <profile-name> returns blank sections.

You have two ways out:

  • Upgrade to FDM 7.3 or later, which adds a Skip CA Certificate Check option when uploading a trusted CA certificate. This is what we did.
  • Stay on 7.2 and use Cisco's workaround: generate your own signing certificate with CA:TRUE, upload it to Entra as a PFX, make it active, and upload it to FDM. You then have to renew that certificate yourself before it expires.

The upgrade was worth doing anyway: newer releases add RA VPN threat detection and fix several actively exploited VPN vulnerabilities.

Step 3: Upgrade FTD, and watch for expired certificates

We went from 7.2.5 directly to 7.6.6, which Cisco supports as a single upgrade. Check your hardware first: the Firepower 2100 series can't run 7.6 and tops out at the 7.4 train, while the 1000 series is fine.

Before you start

  1. Take an FDM backup under Device → Backup and Restore, and download it off the box.
  2. Download the upgrade package for your model from software.cisco.com, not the reimage package.
  3. Run the readiness check in Device → Updates → System Upgrade.
  4. Plan a maintenance window. A single box reboots, so internet access and the VPN go down for 45–90 minutes. Never power-cycle it mid-upgrade.
  5. Go to Objects → Certificates and look for any certificate with an expiry date in the past. The readiness check didn't catch the one that broke our upgrade.

The failure we hit

The upgrade ran to the final stage and then failed. To find out why, check the status and the upgrade logs:

> show upgrade status detail
> expert
$ sudo su
# ls -lt /ngfw/var/log/sf/
# grep -iE "error|fatal|fail" /ngfw/var/log/sf/<upgrade-folder>/main_upgrade_script.log | tail -n 40

The log showed 800_post/100_ftd_onbox_data_import.sh failing with "The chosen certificate has already expired." The new version installed fine, but re-importing the FDM configuration hit an expired certificate that 7.2 had tolerated and 7.6 rejected.

The culprit was DefaultWebserverCertificate, the self-signed certificate for the FDM web UI, which had expired two years earlier. show crypto ca certificates didn't list it, because that command only shows certificates deployed to the data plane. FDM keeps its own certificate database, and the upgrade validates all of it.

The fix

  1. Run upgrade cancel to roll back to the old version with your configuration intact.
  2. Create a new certificate under Objects → Certificates → Add Internal Certificate → Self-Signed. You can't renew the system default.
  3. Select the new certificate under Device → System Settings → Management Access → Management Web Server. Your browser session drops and shows a certificate warning, which is expected.
  4. Check the other places a certificate can be selected (RA VPN device identity, identity policy, SSL decryption), then delete any expired custom certificates.
  5. Back up again and rerun the upgrade.

Step 4: Configure Entra ID

The gallery app does most of the work, and you can enforce MFA without an Entra ID P1 licence. In the examples below, the VPN address is vpn.example.com and the new connection profile is called VPN-SSO.

Create a new connection profile rather than converting the old one

The connection profile name is part of both SAML URLs, so pick it once and use it everywhere with the same capitalisation. A new profile also lets you test with one user while the old one keeps working.

Add and configure the app

  1. In the Entra admin center, go to Enterprise applications → New application and add Cisco Secure Firewall - Secure Client.
  2. Open Single sign-on and choose the SAML tile. If you don't see the SAML settings, you're probably in App registrations instead of Enterprise applications.
  3. Under Basic SAML Configuration, set:
    • Identifier: https://vpn.example.com/saml/sp/metadata/VPN-SSO
    • Reply URL: https://vpn.example.com/+CSCOE+/saml/sp/acs?tgname=VPN-SSO
    • If your VPN runs on a non-standard port, include it in both, for example vpn.example.com:4334.
  4. Download Certificate (Base64), and copy the Login URL and Microsoft Entra Identifier.
  5. Under Properties, set Assignment required to Yes, then assign users under Users and groups.

Without Entra ID P1

Conditional Access needs P1, and so do a few other things you'd expect to use. Here's how we worked around each:

Need

P1 approach

What we did without P1

Require MFA

Conditional Access policy

Per-user MFA, enabled for each VPN user and every admin

Assign users to the app

Assign a security group

Assign each user individually

Lockout threshold

Custom Smart Lockout

Default Smart Lockout (10 failures)

For per-user MFA, turn off Security Defaults first. Then go to Users → Per-user MFA, enable the users, and under Service settings untick remember MFA on trusted devices so every connection prompts. Have users register the Authenticator app at https://aka.ms/mfasetup before cutover.

If Entra Connect uses Pass-through Authentication instead of Password Hash Sync, failed cloud sign-ins still hit AD. Make sure your AD lockout threshold is above Entra's, or switch to Password Hash Sync.

P1 is worth budgeting for later. Location-based Conditional Access alone would have blocked most of this spray.

Step 5: Configure SAML in FDM

FDM needs three objects and one global setting, and the global setting is the one most guides miss.

1. Upload the Entra certificate

Go to Objects → Certificates → + → Add Trusted CA Certificate. Upload the Base64 certificate and tick Skip CA Certificate Check. The checkbox only appears when adding a new certificate, not when editing one. If it's missing after an upgrade, hard-refresh the browser, because it may be showing the old UI from cache.

2. Create the SAML server object

Go to Objects → Identity Sources → + → SAML Server:

  • IDP Entity ID URL: the Microsoft Entra Identifier, https://sts.windows.net/<tenant-id>/, including the trailing slash
  • Sign In URL and Sign Out URL: the Entra Login URL, ending in /saml2
  • Identity Provider Certificate: the certificate from step 1
  • Request Signature: None

3. Set the FQDN and port

There is no Base URL field in FDM. FDM builds the SAML base URL from the RA VPN global settings, which live inside the connection profile wizard.

Edit any connection profile and click Next until the Global Settings page. There, Fully-qualified Domain Name for the Outside Interface becomes the base URL, and Port Configuration sets the VPN port.

We ran the VPN on 4433 because FDM management was using 443 on the outside interface. That port mismatch cost us an afternoon: the SAML login URL came out without :4433 and went nowhere. The cleanest fix is to take FDM management off the outside interface entirely under Device → System Settings → Management Access → Data Interfaces, which you should do anyway, and run the VPN on 443.

4. Create the connection profile

Create VPN-SSO with SAML as the primary identity source, using your SAML object. Use the same address pool and group policy as your existing profile. Give it a group URL, and turn off the option that lets users pick a connection profile at the login page.

5. Verify before testing

> system support diagnostic-cli
# show running-config webvpn | include base-url
# show saml metadata VPN-SSO

The metadata output gives you the exact SP entity ID and ACS URL the firewall uses. Copy them into Entra's Identifier and Reply URL. Matching Entra to the firewall's own output avoids typos in the port, capitalisation, or trailing slashes.

If something fails, run debug webvpn saml 255, retry from the client, and read the output. Run undebug all when you're done.

Step 6: Fix the client-side problems

Once the firewall and Entra matched, SAML worked from a phone and a personal PC but failed on domain laptops. Both problems were on the endpoint, not the firewall.

"Profile settings mandate a single local user"

This appeared after a successful MFA approval. The client profile's Windows Logon Enforcement was set to SingleLocalLogon, and the test PC had a second Windows session still signed in. Run query user, sign off the extra session, and connect again. Keep the setting: it stops a second user on the same PC from riding someone else's tunnel.

"Sent an invalid response", then "validation failed"

On domain laptops, the embedded browser showed a TLS error. Refreshing loaded the Microsoft sign-in page and MFA succeeded, but the client then reported validation failed. The firewall debug showed:

%FTD-3-716164: SAML response relay state missing data integrity hash.

The firewall signs the RelayState it sends to Entra and expects that signature back. Refreshing after the TLS error started a sign-in without the firewall's RelayState, so the firewall rejected the result. The refresh was a symptom; the TLS error was the real problem.

Finding the TLS interception

Opening the Microsoft sign-in page in Edge on the laptop and checking the certificate showed the cause. The certificate chain led to a root named after the laptop's own hostname, ending in "endpoint cert", not to a Microsoft or DigiCert root.

That pattern means local software is intercepting HTTPS by re-signing it with its own root certificate. Things we learned while tracking it down:

  • Pausing the antivirus didn't help, because it wasn't the antivirus. The interceptor was the DLP agent, which generates a signing certificate for each endpoint. ESET's own certificate, for comparison, is named "ESET SSL Filter CA".
  • The certificate's NotBefore date was useless, because interception products often backdate it.
  • Check another laptop. If every managed laptop has the same pattern, it's your own software. If only one does, treat that laptop as potentially compromised: it can read Microsoft sign-ins in cleartext.

The fix: exclusions in the interception tool

SAML doesn't tolerate a man-in-the-middle, so the exclusions are required. In the DLP console's protection exclusions (website exclusions), we added:

vpn.example.com, login.microsoftonline.com, *.microsoftonline.com, login.live.com, *.msauth.net, *.msftauth.net

After the policy synced and the client restarted, the certificate chain went back to Microsoft's and the VPN connected normally. If your interceptor is an antivirus or a secure web gateway agent, the equivalent setting is usually called SSL/TLS filtering exclusions.

Step 7: Add single sign-on and upgrade the client

Switching the SAML login to the user's default browser gives SSO, so users who are already signed in to Microsoft don't type their password again.

Enable SSO

  1. In the VPN-SSO connection profile, change the SAML Login Experience from the embedded browser to Default OS Browser.
  2. In the SAML server object, untick Request IDP re-authentication at login. While it's ticked, Entra has to ask for the password every time.
  3. Deploy, then test with a fresh connection.

You probably don't need the separate external-sso-*.pkg package. It was only required by early AnyConnect 4.10 builds; current clients include the support. It's a 10 KB download, so keep it on hand in case FDM asks for it.

With per-user MFA, expect no password prompt but still an Authenticator prompt. The Windows token only satisfies MFA if the user signed in with Windows Hello for Business. For a firm that just survived a spray, keeping that tap is a reasonable trade-off. Running dsregcmd /status tells you whether laptops are hybrid-joined (AzureAdJoined: YES, AzureAdPrt: YES), which gives the most reliable SSO.

Upgrade AnyConnect 4.10 to Secure Client 5.1

AnyConnect 4.x is end of life. From the Secure Client 5 downloads, take:

Package

Use

Headend Deployment Package (Windows), *-webdeploy-k9.pkg

Upload to FDM; clients upgrade from it

Pre-Deployment Package (Windows), *-predeploy-k9.zip

Install the core VPN MSI on one test laptop first

Profile Editor (Windows)

Edit client profile XML

Skip the ARM64 packages unless you have ARM laptops, and skip the API and transforms packages.

In FDM, the client package is uploaded on the Global Settings page of the connection profile wizard. FDM holds one package per operating system, so the upload button stays greyed out until you remove the old Windows package with its X. Remove and upload in the same session, then deploy.

Clients upgrade themselves on their next connection, without local admin rights. Afterwards, update any application exclusions in your security tools: the install path changes to Cisco Secure Client, and the UI process is now csc_ui.exe.

Step 8: Close the old attack path

SAML only ends the lockouts once nothing else on the firewall still sends passwords to AD.

  1. Delete the LDAP-backed connection profile after all users have moved. As long as it exists, attackers keep spraying AD through it.
  2. Keep the default profiles as sinkholes. DefaultWEBVPNGroup and DefaultRAGroup should authenticate against something that can never succeed, such as an empty local database. FDM 7.6.4 and later fixed a bug that prevented changing these in FDM.
  3. Turn off connection profile selection on the login page, and don't use aliases. Users reach the SAML profile only through its group URL in the client profile.
  4. Watch the counters. Run show aaa-server over the next day. The LDAP reject count should stop climbing. If it keeps rising, something still points at the LDAP server.
  5. Enable RA VPN threat detection. It's available from 7.4.2.1 and 7.6.0, and it shuns IP addresses that repeatedly fail authentication or probe the default profiles. Check with show threat-detection service and show shun.

Housekeeping

  • Send syslog to an external server or SIEM, so the next incident has a record.
  • Switch any remaining LDAP use to LDAPS. Plain LDAP on 389 sends passwords to the domain controller unencrypted.
  • Keep FDM management off the internet.
  • Put certificate expiry dates in a calendar: the VPN certificate, the Entra SAML signing certificate (three years by default), and the FDM web certificate.

Lessons learned

Most of our time went into problems that a short checklist would have caught up front.

Symptom

Cause

Fix

Random AD lockouts

Password spray through VPN, LDAP auth straight to a DC

SAML with Entra ID; delete the LDAP profile

"Failed to generate SAML AuthnRequest"

FDM 7.2 rejects Entra's non-CA signing certificate

Upgrade to 7.3+ and use Skip CA Check

SAML login URL missing the port

FDM builds the base URL from the outside-interface FQDN

Run VPN on 443 or include the port in the FQDN

Upgrade fails at 800_post

Expired DefaultWebserverCertificate

Replace it before upgrading

"Single local user" error

Second Windows session signed in

Sign off the extra session

TLS error, then relay state 716164

DLP agent intercepting HTTPS

Exclude VPN and Microsoft sign-in domains

Pre-flight checklist

  • show aaa-server confirms whether the VPN is the lockout source
  • Confirm whether FTD is managed by FDM or FMC, and which version
  • No expired certificates under Objects → Certificates
  • FDM backup downloaded off the box
  • Users registered for MFA before cutover
  • Certificate issuer for login.microsoftonline.com checked on a managed laptop
  • New connection profile tested with one user before moving everyone
  • Old LDAP profile deleted after cutover

Comments

Popular posts from this blog

Access Denied Error on Exchange Management Shell for Exchange 2013

Microsoft 365 emails to Gmail getting blocked with 550 5.7.1 errors

Handling PDF Size Issues with Protected Files: A Solution Using Microsoft PDF Printer