How we updated our risk engine to stop “slow and low” password list attacks

In the last six months, we’ve seen an evolution in how attackers are launching password list attacks, which in turn is impacting how best to fight these attacks.

It’s become easier than ever to obtain ranges of hundreds of IPs, which makes it possible to masquerade traffic as coming from multiple different sources. Similarly, many of these IPs are registered in the United States. Taken together, this so-called “slow and low” attack weakness the effects of rate limiting and location-based rules.

It’s possible to mitigate these attacks, but it takes a different approach. We’ve put together some best practices implemented some changes to our risk engine, which we’ll unpack in this post.

The good old five-attempt rule

In the past, many attacks could be mitigated by simply rate limiting on the IP-level. For example, Cloudflare recommends blocking an IP for 10 minutes whenever you see more than five failed attempts within 30 seconds. There are also open-source software such as Ruby rack-attack or Python django-defender that achieve the same thing.

But for the scenario described above, this wouldn’t really help. If an attacker has access to a wide IP address space, they can replay a list of stolen passwords at a high rate, but distribute them across many IPs. Your IP-based rules will only see a few failed logins coming in every minute, making you think all is fine. But in aggregate, there actually will be thousands of failed logins.

Attackers staying under the radar

Recently, one of our customers experienced a password list attack that was active for nearly three hours and originated from over 500 different IP addresses. Each IP made between 50 to 500 attempts over the course of the attack. This is (only) roughly three attempts per minute, which would stay under the radar for any rate limiting configured to lock accounts at five attempts. But Castle spotted that there were actually hundreds of thousands of login attempts during over the course of three hours, which enabled us to help the customer prevent the attack.

Using other approaches, you’d need a threshold of three attempts would be needed to lock out the majority of those IPs. But by lowering the IP thresholds, you’ll also start blocking legitimate logins, especially ones using mobile networks like AT&T and Verizon, where IPs are shared by many users.

Powering up your defense

To mitigate these attacks, you should do two things, which we’ve also implemented in our risk engine here at Castle:

  • Analyze attempts on the ASN level instead of IP. You can use a free IP address to ASN database to do the lookups.
  • Analyze the behavior of the attempts—not only the number and frequency: Were they made for (non-)existing user accounts? Did they originate from locations and devices that haven’t previously accessed the attempted accounts? Did they update any profile data once they gained access?

Updates to Castle

In the last month, in response to these trends, we’ve been rolling out a set of updates to our risk engine to make it better at detecting things on the ASN level–in addition to the existing user-, device-, IP- and ISP-level.

If you’ve already implemented Castle, you’ll automatically benefit from these updates. Any login that accesses under these malicious circumstances will be immediately marked as “Malicious” by Castle.

If you’d like to enable your integration, make sure you subscribe to Incident webhooks, and log out users based on the deny action from Adaptive Authentication API.

If you’re curious about learning more about these attacks and how to prevent them and others, reach out!