A person interested in security, performance and accessibility.

It's imperative software developers protect credentials with great care, like properly hashing low entropy values (PINs, passwords, or passphrases) with slow cryptographic hashing algorithms like Argon2 or Bcrypt. They're specifically designed for deriving cryptographic keys based on low entropy values, with the exception of Bcrypt.

Multiple factors of authentication is crucial to protect accounts. Such as knowledge of a secret, and possession of something; hopefully third-parties have none of the factors.

Even if the cryptography is properly implemented, and other security practices are in place, there's usually still another popular attack vector: authentication.

Just Use CAPTCHAs!

Often, developers will use CAPTCHAs to thwart automated scripts.

Usually it's still possible to attack a lot of services by trying well known passwords/passphrases against a bunch of accounts. Some services attempt to prevent this with CAPTCHAs(official site).

One thing I've noticed is that CAPTCHAs are either accessible or sufficiently resistant to automated actions. Often it's not both. Sometimes it's neither! Even though I don't have any disabilities, I still have a hard time completing them. Which generally means people with disabilities will.

Google's reCAPTCHA a lot of the time doesn't like Tor network activity, often rejecting valid CAPTCHA answers due to “possibly automated queries”. Usually the solution I found is to switch up the exit node. It's an issue with popular proxies and VPNs, not just Tor users. Google knows when you're using Tor.

Unfortunately, I don't know of any reliable free open-source privacy respecting alternatives to Google's CAPTCHAs.

So CAPTCHAs may not be the best choice.

My Solution

The Out-Of-Band Account

For each set of credentials that is stored, there's also an unique foreign account associated with it, this could be a email, XMPP or phone number that the authentic individual is in possession of.

This is also known as out-of-band authentication.

The Data

There has to be some sort of data sent to the foreign account to prove they have access to it. The data MUST be ephemeral, and unpredictable. It could be a temporary, and secret login page where a few login attempts are permitted.

To securely store the data, and verify the foreign account access data, it must be hashed properly. Generally the secret is low entropy, so we should store it with Argon2 or Scrypt.

However if the data comes from a CSPRNG output with greater than or equal to 128 bits of entropy, we use an easy to compute hashing function. Take the cryptographic BLAKE2 hashing algorithm for example.

For defense in depth or as an alternative strategy: Use asymmetric key cryptography to ensure only the authentic individual may access the data when it arrives at the out-of-band destination. This could be sent to the associated foreign account or displayed.

Example ephemeral and unpredictable link:


The “Locking” Mechanism

There are two crucial pieces to the puzzle; the foreign account, and the data. We have one final piece to gather.

What are we going to do with those two pieces? They can be used as a form of two-factor authentication.

By definition “locking” means to apply that 2FA. Of course we could constantly apply it(preventing nearly all malicious authentication attempts), however ... we can try to make educated guesses to only apply the 2FA when it's possible there is an attack on the account.

Which means it's possible to make the accounts a lot more secure while retaining usability.

When, and How Long to Lock

Locking the IP address should happen for a given

We can lock an IP that attempted to authenticate and failed a certain number of times within a certain time period. If we lock an IP, it's global. Meaning that IP is not allowed to attempt to authenticate on any accounts without verifying foreign account access. This goes for whitelisted IPs as well.

There is one other way to handle IPs. Each account could have whitelisted IPs that avoid the lock(only if the whitelisted IPs aren't locked), while any unrecognized IPs are automatically required to go through lock, even if the IPs themselves aren't locked. This could provide some better security while still retaining some usability.

Another method is locking by account. If a certain number of authentication attempts fail within a certain time period, it'll be locked. Meaning no IPs may attempt to authenticate on this account. That includes whitelisted IPs.

The only effective way of defending against attacks is to use both methods. Locking by IP and account, preferably with the same allowed authentication fail attempts before locking.

We can't completely rely on the first method because most experienced attackers know that they can just switch up their IP with a proxy.

We also can't completely rely on the second method because one IP could just attack all of the accounts. Instead we use both methods to prevent both issues.

However it's better to only have the second method than to only have the first. And it's best to have both.

  1. If an account is allowed 3 failed attempts within 24 hours, and an IP is allowed 6 failed attempts within 24 hours ... they can use one IP to attack two accounts.

  2. If an account is allowed 6 invalid authentication attempts within 24 hours, and an IP is allowed 3 failed attempts within 24 hours, we can use two IPs to attack one account. This can be worse than 1) because more attempts are available to each account.

For how long the account or IP is locked could fixed, incremental(depending on how many times it was previously locked), or randomized.

There are a few other things to take into consideration. You could make accurate educated guesses by determining how many requests there are to authenticate with which IP, and which account. Monitor and automatically lock all accounts for a certain period of time if you're 99% sure there is a possible attack on a bunch of accounts and warn the users that there is probably an attack that was prevented.

It's one area I'm still exploring, how to accurately determine whether there are attacks ongoing. (Although from my understanding it's extremely hard, it would require a lot of math, possibly even an AI.)

This was my alternative for authentication forms. This isn't meant to replace CAPTCHAs, it's meant to avoid them as much as possible and provide a more secure and accessible solution when authenticating.

The most secure solution is to always apply the 2FA, use asymmetric cryptography and a high entropy piece of data, such as the software token attached to a link. But this is too inconvenient for average users.

Take note that if you're not already logged into your email assuming that's what you use for the foreign account, then the email service could require CAPTCHAs during the sign in process.

If you have any questions or you'd like to discuss anything, contact me via email, Mastodon, the forum, DEV.to or XMPP.