[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: cookie verification



Hello (and sorry for the long post),

As promised, here is the cookie mechanism:

    H = hash(PRIV || src IP || src port ||
             dst IP || dst port || I-COOKIE ||
             PRIV)
    D = des(DKEY, AGE || AGE || AGE || COUNTER)
    R-COOKIE = H XOR D

H is, for instance, an MD5 hash of the data shown above,
where PRIV is a private octet string.  (I-COOKIE is
omitted when creating an initiator cookie).
D is an encrypted DES block consisting of three
identical 16-bit AGE fields and a COUNTER field.
AGE is a 16-bit value that depends on the cookie
creation time (e.g. seconds_since_boot MOD 2^16),
while COUNTER is a value that increases for each
cookie generation (and wraps).

A cookie can be verified by calculating H (which
requires only public data and no storage for the
verifier) and XORing with the cookie to reveal D.
D is decrypted using DKEY to obtain an 8-byte block.

This is the main part:  the DES block structure is
verified to have the proper structure, i.e. it must
consist of three identical 16-bit values followed
by some 16-bit value.  If not, this definitely is
not a cookie we created (using DKEY and PRIV as
the private secret).

Probability of interpreting a random cookie as a
valid one is 2^32, which can be made lower by
doing better checking of the claimed AGE and
COUNTER values.

The cookies generated in this way have the following
properties:
    1. They depend on the parties in question
       (definition of H), and date and time (AGE,
       COUNTER).
    2. Each generated cookie is unique, save for bad
       luck.  Since COUNTER increases each time, a
       generated cookie is different even if the
       parties are the same (=> H is the same) and
       AGE is the same.  [zero cookie checks have to
       be made; increase counter and regenerate if
       zero cookie was accidentally generated.]
    3. Given a cookie, we can determine:
       (a) whether it was created by us (using the
           current PRIV and DKEY as private values).
       (b) the approximate age of the cookie, using the
           AGE field.
    4. The cookies are unpredictable to an outsider
       (DKEY, PRIV).
    5. Cookie generation and verification are reasonably
       fast (one hash calculation, one MD5 calculation).
       [actually twice the work for verification, because
       DKEY, PRIV must be changed periodically.]

A simpler approach to cookie generation uses a hash
which includes a private secret (plus public data) and
changes the secret once in a while to protect against
attacks such as "cookie jar".  This is problematic for
two reasons:
    1. Cookie age estimations will be rough, since we
       can only know whether the cookie was created
       using the current secret or not (or with the
       previous one, if we try that also).
    2. Each change of secret consumes entropy, since
       the secret must be unpredictable.  Secret bytes
       are expensive without hardware assistance.

The scheme I described is better because we can estimate
cookie age more accurately, and can choose the private
secret refresh frequency independently (PRIV, DKEY) of
the age resolution we desire.  (To conserve entropy,
we could also set PRIV=DKEY.)

Cookies are not a strong security feature: the worst
case scenario is that the attacker will obtain DKEY and
PRIV, and will be able to create cookies that we will
happily accept.  This will allow denial-of-service attacks
until the values are changed.  Of course, DKEY and PRIV
MUST NOT be used for anything else in the protocol!

But considering the effort of the attacker:  he must
cryptanalyze cookies we create to obtain DKEY and PRIV.
I'm no cryptanalyst, but it seems that the effort spent
in doing that costs much more than the gain of being able
to do denial-of-service attacks on the server host for
a limited period of time (even if update frequency is
something like 15 minutes).

(The cookie generation would probably be more secure
if we used HMAC-MD5 (with PRIV as the key) instead of
just an MD5-hash.  But that needs more computation
for little gain, assuming that the current scheme is
hard enough to make cracking not worthwhile.)

Using this cookie scheme, Matsuura's mode could avoid
cookie the kind of "cookie jar" attack without storing
extra state.  We would simply calculate "AGE" of
responder cookie in the third message of the exchange,
and ensure it is fresh enough (configurable limit).
If not, discard the message.

Was that complicated enough? ;-)

Sami

--
Sami Vaarala (sami.vaarala@netseal.com)
NetSeal Technologies
http://www.netseal.com/




References: