Re: New Whitepaper: Anti Brute Force Resource Metering
From: Amit Klein (AKsecurity) (aksecurity_at_hotpop.com)
Date: Tue, 22 Mar 2005 18:50:06 +0200 To: "Gunter Ollmann (NGS)" <firstname.lastname@example.org>, email@example.com
On 21 Mar 2005 at 18:53, Gunter Ollmann (NGS) wrote:
> Hi List,
> It's been a couple of months since my last whitepaper, so time for a new
> one. This new whitepaper focuses upon a method known as "resource metering"
> to actively restrict (and possibly prevent) many brute force guessing attack
> vectors that target custom web authentication processes.
> The paper is now available from the NGS website:
> As always, I'm happy to discuss the topic further and would value
> discussions about the techniques talked about in the paper.
Hi Gunter (+BugTraq)
First, nice paper. Well written.
One thing that I think can perhaps be improved is the amount of
persistent data (the seed values) that the system keeps (in memory?).
My thought is to replace the seed value with something a bit more
complex, as following:
The system will indeed generate a seed value, yet it will not store
it. It will send it to the user, and then discard it (so it does not
consume space). The seed will be calculated as following:
let x = random digits ^ ":" ^ date_and_time [microsecond granularity]
seed = x ^ ":" ^ HMAC(key,x)
I also require that the client side changes a bit the way it answers
the challenge. Instead of
alg# ^ ":" ^ seed ^ ":" ^ userID ^ ":" ^ date ^ ":" ^ random data
I require that the attempted password be part of the data:
alg# ^ ":" ^ seed ^ ":" ^ userID ^ ":" ^ PASSWORD ^ ":" ^ date ^ ":"
^ random data
The user submits this string (such that its SHA-1 has the first N
bits zeros), together with the username and the password.
The server verifies that:
1. The last field of the seed is the HMAC with the server key of the
first two fields.
2. The time field in the seed is not too old (e.g. in the last 5
3. The username and password that are submitted are indeed embedded
in the hashcash string
4. And of course, that the hashcash string does indeed hash into a
leading N zeros value.
Note that the server, in this suggested scheme, cannot disallow
sending the same seed again and again (during the 5 minutes lifetime
of the seed value). It also has no per-account memory, so there's no
"penalty" for attackers.
It should be noted that with this modified scheme:
a. A calculation done for one username+password pair is useless for
another pair (perhaps with the same username), because both the
username AND the password are part of the hashcash string.
b. Using server signed seed with time limit ensures that a seed
cannot be replayed too many times (and over a long period of time).
This prevents an attack wherein th attacker invests a lot of time in
preparing many "good" strings (in this scheme, for example, the
attacker can calculate hascashes for many usernames with a single
password), then trying those values periodically.
A comparison of the two methods (the original one, and the modified
The original method uses per-account list of seeds.
The modified method uses only a global key.
The original method does keep the password out of the payment system.
The modified method must use the password (thus it somewhat
complicates the process - it's no longer two independent flows).
The original method can alter a specific account behavior.
The modified method (on account of not having a per-account data)
cannot alter a specific account behavior.
We see, therefore, that there is a tradeoff between the original
method (space consuming, more flexible, simpler) and the modified
method (compact, less flexible, somewhat more complex).
Regarding the fact that the password is used in the modified method:
As I said above, this is both less elegant, and in some cases may be
considered less secure (the original method was potentially unexposed
to the password).
However, a simple modification to the modified method ;-) can take
care of this shortcoming. Instead of providing the username and the
password, it is enough to provide, say:
salt ^ ":" ^ HASH(username ^ ":" ^ password ^ ":" ^ salt)
the system can then send a pass/fail status to the "normal"
username+password authentication system, along with the above value,
which the authentication system can (and must) verify. That is, the
system doesn't have to know the username and the password. It is
enough for it to verify that the hashcash was calculated for the
specific username and password that are provided.
While this indeed takes care of the username+password exposure in the
system, it also necessiates a tighter integration with the standard
authentication system (which now must verify the hash value).