Blocking Low and Slow botnet authentication attacks against exposed SSL VPN portal.
Over the past year, the amount of low and slow botnet authentications to numerous end-customer SSL VPN portals has been increasing. This is where the attacks do not trip the native brute force measures in a FortiGate and the wave of attacks comes in groups of between 3 and 5 public IP addresses for a day or so, then shift to new IP groups. Time intervals of each hit can be from 10 minutes to 20 hours.
So far, we have implemented in the FortiGates the Automation methods to auto block and quarantine any SSL VPN attempts for generic usernames that are not in use (admin, root, sslvpn, test, testuser, user, etc....) Some end clients have 50 or more new blocked IP addresses added to their FortiGate daily! Where this was implemented we see the volume of attacks drop from up to 1,000+ in a 24 hour period to under 100.
We also already employ the method of pinning the SSL VPN interface to local loopback interface on the FortiGate, then use firewall policies to help block access to a variety of IP reputation lists, block lists, swatfeeds, IPS policies, DOS policies, and so forth. (This was a huge help to knock down the volume of attacks!)
Here is example of one FortiGate Failed Authentication attempts. My human eyes can see the pattern rather quickly, and daily we look at reports for the worst offenders and add them to our swat feed that our managed firewalls all subscribe to block those IP addresses. FYI-none of these usernames are actual usernames in their domain.
Any ideas? If the logs gave code or reason such as 'user does not exist', this would be easy!
Does Fortinet not offer the ability to control the 'login-attempt-limit' time window? It seems to be too short! Should be tiered options. 2 failures in 60 seconds, quarantine for 1 to 5 minutes, 5 failures in 24 hours, then quarantine IP for 24 hours.
I have had some thoughts, but the scripting and automation is beyond our abilities. Such as "block/quarantine IP for non-existing user" or "x number of failed attempts in a 24 hour period".
We use FortiAnalyzer inhouse and FortiSIEM via a partner.
One of the things you can implement is to add geo block on SSL VPN and also create local in policy for geo block If your users are only in a particular country, you can block all other countries. This would reduce attempts coming from outside your country.
We already have the SSL VPN portal more locked down than your local-in example. We use as I mentioned the method of pinning the SSL VPN services to a loopback IP, then use NAT firewall policies to protect the service with DOS, IPS, Geo blocking, IP Reputation blocking, and Internet Service Blocking (Tor, Botnet, Malicious, spam, Phishing, Proxy, etc.), we have multiple external IP block lists as well as I mentioned. This method is a few steps above the abilities of the FortiGate local-in policies.
We do have the login attempts quarantining failed logins very aggressively, with long time-out periods. If a real user is blocked, they know to call helpdesk.
And we also have used FortiGate's Automation feature to auto blacklist failed user attempts for obvious bots with usernames like root, admin, administrator, etc as I highlighted in my original post. We have automation action also post back to us the public IP being blocked so we have it in a general list to review.
What I was asking for was an automation strategy to detect these patterns of failed logins with a tool other than our human eye, if there is anything we can do other than plucking out the higher volume networks to add to our swat feed I am all ears! We have fortiSIEM and FortiAnalyzer at our disposal.
Otherwise we are doing everything we can to protect a customer's environment, it is just a lot of failed login noise being generated.
We are then also reliant on the end customer's adhiance to our policies of strong passwords and 2FA/MFA for all remote logins. We even ask end customer to have all executives and key employees at a minimum to have logins to their domains that are not the same as their mailbox user or obvious first initial + lastname for their system usernames.
> Should be tiered options. 2 failures in 60 seconds, quarantine for 1 to 5 minutes, 5 failures in 24 hours, then quarantine IP for 24 hours.
I would definitely support such feature, but as no such option is available currently, the only way to get it would be a new feature request, which is something you'd have to do through your Fortinet sales contact.
> "block/quarantine IP for non-existing user"
This is also a good idea, but you will run into authentication protocol-specific limitations. RADIUS never explains why an attempt failed in Access-Reject (or extremely rarely, such as when a password expired and renewal is available with MSCHAPv2), and neither does LDAP give special responses to failed bindRequest in most cases (the most used LDAP variant, Microsoft's, does not make a distinction between "wrong password" and "nonexistent user"). This of course makes sense, differentiating between the two would be information leakage.
In theory, some additional user lookup in LDAP could be implemented to establish if a username exists and then have the FortiGate act on that result, but this would again be a new feature to be requested and implemented.
Switching to SAML could be an interesting option. If an attacker never succeeds authenticating on the IdP's login, they will never get back to the FortiGate to finish their connection attempt. This would likely severely cut down the occurence failed logons in FortiGate's own logs.
With that said, this is technically just moving the problem elsewhere, to the IdP. But perhaps if you trust the IdP's brute-force protections more (or can set some additional protections there), this could be be a perfectly valid solution.
We are using the FortiGate Automation feature to test failed logins for specific/generic usernames that the botnets tend to lead with, add those attempts IPs to a well crafted IP address object and address group we name 'SSLVPN_AutoBlock', Our automation action also sends us the blocked IPs to a list that we review on occasion. Similar to a honeypot idea and we put some of those IPs and networks to a swat feed that our client firewalls subscribe to block as well. We block these IP addresses from ever reaching any published system to the internet, not just for protecting SSL VPN. You must be careful, as most FG models have a max limit for number of address objects, we have seen some sites add 100 blocked IP address objects in a 24 hour period. So next we are looking for a way to auto remove these IP addresses. We have been using the Quarantine function and setting the expiration out to over 24 hours.
Example: diag user quarantine add src4 %%log.remip%% 86400 admin
Quarantine however just disrupts an authentication attempt, it doesn't get used in firewall policies.
Then we use a firewall policy using the address group before the allowed SSL VPN Loopback interface. (again, one of the many reasons why the loopback approach is better than the native root SSL interface.)
We had this idea on our own, but found other like minded people in this forum and reddit that were doing the same. Found all the Automation's limitations real quick to!
Example lab/internal setup of our inbound firewall policies ahead of the allowed SSLVPN Interface:
the last policy also has set reputation-minimum 3.
The Fortinet Security Fabric brings together the concepts of convergence and consolidation to provide comprehensive cybersecurity protection for all users, devices, and applications and across all network edges.