Slow Down Online Guessing Attacks with Device Cookies

Intro
This is by no means my idea. I’ve overheard the term “device cookie” from Marc Heuse at PasswordsCon 14, also Alec Muffett mentioned “datr” cookie from Facebook in his talk at the same conference. So, the only purpose for this writing is to put the idea into ready-to-implement condition and to raise public discussion about its security or may be insecurity and scarce usefulness.

The main idea behind the protocol is to issue a special “device” cookie to every client (browser) when it is used to successfully authenticate a user in a system. The device cookie can be used to:
 * Distinguish between known/trusted and unknown/untrusted clients
 * Establish universal temporary lockouts for all untrusted clients
 * Lockout trusted clients individually.

Why?
There are few well-known ways to deal with online attacks:
 * Temporary account lockout
 * Use CAPTCHA to slow down attacker

Other tricks, like producing confusing answers for attacker are more like “security by obscurity” and cannot be used as first-class protection mechanism.

Temporary account lockout after several failed attempts is too simple of a target for DoS attacks against legitimate users. There is variation of this method that locks out pair of account/IP. It is better in regarding to DoS issues but have security downsides:
 * Attacks from botnets can be effective
 * Attacks through proxies can be effective

Moreover, it is not so trivial to implement account/IP lockout. Consider multiple proxies with chaining addresses in “X-Forwarded-For” header or IPv6.

The method described in this writing may be viewed as variant of account/IP blocking. But it proposes to use a browser cookie instead of an IP address. Thus it may be more predictable from security perspective and easier to implement.

Protocol
Protocol parameters:
 * T - time period
 * N - max number of authentication attempts allowed during T

The sign ∎ hereafter states for end of algorithm.

Entry point for authentication request
 * 1) if the incoming request contains a device cookie:
 * a. validate device cookie
 * b. if the device cookie is valid and not in the lockout list
 * authenticate user∎
 * 1) if authentication from untrusted clients is locked out for the specific user
 * reject authentication attempt∎
 * 1) else
 * authenticate user∎

Authenticate user
 * 1) check user credentials
 * 2) if credentials are valid
 * a. issue new device cookie to user’s client
 * b. proceed with authenticated user
 * 1) else
 * a. register failed authentication attempt
 * b. finish with failed user’s authentication

Register failed authentication attempt
 * 1) register a failed authentication attempt with following information: { user, time, device cookie (if present) }.
 * 2) depending on whether a valid device cookie is present in the request, count the number of failed authentication attempts within period T either for
 * a. all untrusted clients
 * or
 * b. a specific device cookie
 * 1) if number of failed attempts within period T > N
 * a. if a valid device cookie is presented
 * put the device cookie into the lockout list for device cookies until now+T
 * b. else
 * lockout all authentication attempts for a specific user from all untrusted clients until now+T

Issue new device cookie to user’s client Issue a browser cookie with a value like “LOGIN,NONCE,SIGNATURE”, where
 * LOGIN - user’s login name (or internal ID) corresponding to an authenticated user
 * NONCE - nonce of sufficient length or random value from CSRNG source
 * SIGNATURE - HMAC(secret-key, “LOGIN,NONCE”)
 * secret-key - server’s secret cryptographic key.

Validate device cookie
 * 1) Validate that the device cookie is formatted as described above
 * 2) Validate that SIGNATURE == HMAC(secret-key, “LOGIN,NONCE”)
 * 3) Validate that LOGIN represents the user who is actually trying to authenticate