List Info

Thread: session ID collision (security issue) & cookies (Expires vs. Max-Age)




session ID collision (security issue) & cookies (Expires vs. Max-Age)
user name
2006-02-08 08:22:49
> === Max-Age vs. Expires ===
>
> A CherryPy-based app sends the following HTTP response
header:
>
>    Set-Cookie:
sessionID=1463e23a0b32c0a036b10a83ded76f9245b4a3b4;
> Max-Age=31104000; Path=/; Version=1;
>
> This cookie does not write out a cookie to disk on
Internet Explorer
> 6.0 (and likely earlier versions).  Internet Explorer
will pass the
> cookie back and forth to the server will the browser is
still open.
> When you close and re-open the browser, the session is
lost.  The
> cookie was never written to disk.
>
> A "correct" (I'll explain the quotes in a
minute) header - for example
> the HTTP response header returned by www.cherrypy.org -
seems to be:
>
>    Set-Cookie: trac_session=c5429b9a8a69401200446c23;
expires=Mon,
> 27-May-2019 23:53:14 GMT;
>
> Note the "expires" vs "Max-Age".
>
> This header will write the cookie to Internet
Explorer's Cookies
> folder.  This cookie is preserved between
closing/opening your browser.
>
> I put "correct" in quotes because according
to RFC 2109
> (http://www.faqs
.org/rfcs/rfc2109.html), Max-Age should be used in
> cookies, not the older Expires.  However, only Expires
appears to work
> on Internet Explorer.
>
> I'm really surprised this hasn't come up before...I
have a hard time
> believing I'm the only one trying to support Internet
Explorer sessions
> that last longer than a single browser window being
open.
>
> Here's my quick fix in sessionfilter.py:
>
>     #cookie[cookieName]['max-age'] =
sess.sessionTimeout * 60
>     t = datetime.timedelta(seconds =
sess.sessionTimeout * 60)
>     expirationTime = datetime.datetime.now() + t
>     cookie[cookieName]['expires'] =
expirationTime.strftime("%a,
> %d-%b-%Y %H:%M:%S GMT")
>
> (this isn't totally correct - this is setting a local
time, not the GMT
> time...)

I've updated the session_filter to use "expires"
instead of "max-age"
(changeset [963])

> === Session ID collision ===
>
> Digging through my debug logs I noticed session ID
collisions.  It
> looks like a ticket is sitting at the bottom of the
queue about this
> (http://www.cherryp
y.org/ticket/408).
>
> I'm really surprised to see collisions since it should
theoritically be
> very rare.  But my log shows 113 instances of newly
created session IDs
> that already exist in my database, causing two users to
end up with the
> same session ID.  On diggdot.us it's not a tragic
security flaw since
> I'm not storing any serious data per user, but on some
other sites this
> could expose some potentially private data to the wrong
user.  Seems
> like a major security issue.
>
> Note that I'm using a very long expiration time, so my
sessions table
> is growing quite large.  But it's still surprising to
see that many
> collisions.  For a fix, the generateSessionID()
function could check to
> see if the new session ID already exists and try
creating a new ID if
> it does.
>
> I'm using CP 2.1.1, but I see these issues still exist
in CP 2.2.0beta.

Well, the default session id generator uses
"sha.new('%s' %
random.random()).hexdigest()" to generate the session
id. This
generates a "fairly random" 40 character string.
I'm not an expert on statistics but I would expect
collisions to be
likely to happen only on a very, very large set of visitors
... 113
collisions seems very unlikely ... How many session ids do
you have ?
Are you sure it's not another problem (like the same session
id from
the same user somehow appearing twice in your DB ...) ?

A few more comments:

- In the current trunk you can specify your own session id
generation
function by passing it via
"session_filter.generate_session_id".

- If someone wants to suggest a better session id generator
than the
one we currently use (provided it's fast) I'm not against
changing the
current one.

- Unfortunately, checking that the generated session id
doesn't already
exist can be very expensive if there are lots of sessions
(especially
for the file backend) so this approach seems unpractical ...

Remi.

session ID collision (security issue) & cookies (Expires vs. Max-Age)
user name
2006-02-08 09:35:19

> Well, the default session id generator uses
"sha.new('%s' %
> random.random()).hexdigest()" to generate the
session id. This
> generates a "fairly random" 40 character
string.

Not so sure.

random.random() has a large period but it seems there could
be a problem 
in a multi-threaded environment as the python doc suggests:

"The functions supplied by this module are actually
bound methods of a 
hidden instance of the random.Random class. You can
instantiate your own 
instances of Random to get generators that don't share
state. This is 
especially useful for multi-threaded programs, creating a
different 
instance of Random for each thread, and using the
jumpahead() method to 
ensure that the generated sequences seen by each thread
don't overlap."

Remi, is this what you do?

- Sylvain
session ID collision (security issue) & cookies (Expires vs. Max-Age)
user name
2006-02-08 13:52:38
we generate unique ids with:

random.getrandbits( size )

where size is a integer of the desired lenght. Setting that
to say 128
makes the chances of collision practically nil.

(we also compute a hexdigest of it to make it a bit shorter)

[1-3]

about | contact  Other archives ( Real Estate discussion Medical topics )