librelist archives

« back to archive

Security of secure sessions

Security of secure sessions

From:
Jacob Peddicord
Date:
2011-08-15 @ 02:09
I did a little digging into the source of Flask and Werkzeug, and
found some interesting/scary things regarding sessions and secure
cookies. I'd love to be proven wrong on these, so nitpick away. :)

1) Werkzeug uses Pickle as the default serialization method, and Flask
doesn't override it. This means that should the application secret key
be revealed, remote code execution is possible. It's a small risk if
you have a good secret, but I'd much rather confine the risk to a
forged session rather than a compromised system. The Werkzeug docs
mention this[1], and recommend subclassing SecureCookie and setting
serialization_method to json if available. This is something that
should be done by default; unless the json module isn't available.

2) In terms of the data itself, a temporary session is permanent and a
permanent session is temporary. What I mean by this is that while a
temporary session's cookie does expire at the end of a browser
session, its data could be used indefinitely.

For example, let's say I store the username "jacob" in a session using
all defaults. This session is signed, and expires when the browser
closes. But let's say I'm at a public library, and forget to close the
browser. The person after me could simply write down the contents of
my cookie and authenticate as me for as long as they pleased. Changing
my password/credentials would do nothing, as it's not stored in the
session.

This is not a problem with "permanent" cookies, which have their
expiration added to the cookie data and signature by Werkzeug[2]. This
confines the period of which my session could be forged to its
expiration. There are a couple of possible fixes:

a) in Flask: make the default temporary sessions expire after a day or
so, perhaps using the already-existing "permanent_session_lifetime"
option (though the name doesn't quite fit).

b) in applications: make it up to the developer to subclass their own
session, or to implement their own session invalidation. If this is
the case, the Flask documentation for secure cookies should note that
by default, sessions are indefinite unless there is some
time/database-linked variable in there.

Like I said, if I've got this all wrong, feel free to say so.
Otherwise, let's discuss some possible solutions. :)

Cheers,
Jacob

[1] http://werkzeug.pocoo.org/docs/contrib/securecookie/#security
[2] 
http://werkzeug.pocoo.org/docs/contrib/securecookie/#werkzeug.contrib.securecookie.SecureCookie.serialize

-- 
Jacob Peddicord
http://jacob.peddicord.net/

Re: [flask] Security of secure sessions

From:
Armin Ronacher
Date:
2011-08-15 @ 06:29
Hi,

On 8/15/11 4:09 AM, Jacob Peddicord wrote:
> serialization_method to json if available. This is something that
> should be done by default; unless the json module isn't available.
Just that it does not work in practice because everybody depends and
requires pickle (See every pyopenid for instance).  Also automatic
switching is a horrible idea since it means that a deployment chance
renders your sessions invalid.

> 2) In terms of the data itself, a temporary session is permanent and a
> permanent session is temporary. What I mean by this is that while a
> temporary session's cookie does expire at the end of a browser
> session, its data could be used indefinitely.
That is pretty much by design.

I had the idea to replace the sessions system with itsdangerous but it
turns out that in the real world pickled sessions are required and that
sessions that do not expire are not a problem.  With encrypted traffic
the session can't leak anyways and unencrypted communication is a
security problem anyways.


Regards,
Armin

Re: [flask] Security of secure sessions

From:
Jacob Peddicord
Date:
2011-08-15 @ 13:35
On Mon, Aug 15, 2011 at 2:29 AM, Armin Ronacher
<armin.ronacher@active-4.com> wrote:
> Just that it does not work in practice because everybody depends and
> requires pickle (See every pyopenid for instance).  Also automatic
> switching is a horrible idea since it means that a deployment chance
> renders your sessions invalid.

Okay, fair enough; I'll just override this in my own application.

> sessions that do not expire are not a problem.  With encrypted traffic
> the session can't leak anyways and unencrypted communication is a
> security problem anyways.

If I may argue my point a bit more:

Any session system can be compromised with unencrypted traffic, so
that's probably outside the scope of this. What concerns me is the
damage that can be done once a session has been stolen.

With server-side sessions, the session can easily be invalidated.
That's not possible with secure cookies, so there needs to be a way
for a cookie to invalidate itself. This is already done for permanent
cookies: since they have an expiration, they will be invalid after a
set amount of time, and the risk is confined.

However, temporary secure cookies completely sidestep this by making
them valid forever. The fact that the cookie expires on the browser
session implies that it shouldn't be valid for much longer than that.
What I'm saying is that *no* secure cookie should ever last forever.

I'm willing to write a patch to change this behavior if it would be accepted.

Cheers,
Jacob


-- 
Jacob Peddicord
http://jacob.peddicord.net/

Re: [flask] Security of secure sessions

From:
James Thornton
Date:
2011-08-15 @ 13:58
I have been playing around with the idea of using timestamps as a type
of nonce inside an AES encrypted cookie and comparing them on each
request to the value stored in Redis to see if they are out of sync --
see 
http://flask.pocoo.org/mailinglist/archive/2011/6/16/using-timestamps-to-prevent-session-hijacking/
.

Thoughts?

- James

On Mon, Aug 15, 2011 at 8:35 AM, Jacob Peddicord <jacob@peddicord.net> wrote:
> On Mon, Aug 15, 2011 at 2:29 AM, Armin Ronacher
> <armin.ronacher@active-4.com> wrote:
>> Just that it does not work in practice because everybody depends and
>> requires pickle (See every pyopenid for instance).  Also automatic
>> switching is a horrible idea since it means that a deployment chance
>> renders your sessions invalid.
>
> Okay, fair enough; I'll just override this in my own application.
>
>> sessions that do not expire are not a problem.  With encrypted traffic
>> the session can't leak anyways and unencrypted communication is a
>> security problem anyways.
>
> If I may argue my point a bit more:
>
> Any session system can be compromised with unencrypted traffic, so
> that's probably outside the scope of this. What concerns me is the
> damage that can be done once a session has been stolen.
>
> With server-side sessions, the session can easily be invalidated.
> That's not possible with secure cookies, so there needs to be a way
> for a cookie to invalidate itself. This is already done for permanent
> cookies: since they have an expiration, they will be invalid after a
> set amount of time, and the risk is confined.
>
> However, temporary secure cookies completely sidestep this by making
> them valid forever. The fact that the cookie expires on the browser
> session implies that it shouldn't be valid for much longer than that.
> What I'm saying is that *no* secure cookie should ever last forever.
>
> I'm willing to write a patch to change this behavior if it would be accepted.
>
> Cheers,
> Jacob
>
>
> --
> Jacob Peddicord
> http://jacob.peddicord.net/
>



-- 
Bulbflow: A Python framework for graph databases (http://bulbflow.com)

Re: [flask] Security of secure sessions

From:
Jacob Peddicord
Date:
2011-08-15 @ 14:09
On Mon, Aug 15, 2011 at 9:58 AM, James Thornton <james@jamesthornton.com> wrote:
> I have been playing around with the idea of using timestamps as a type
> of nonce inside an AES encrypted cookie and comparing them on each
> request to the value stored in Redis to see if they are out of sync --
> see 
http://flask.pocoo.org/mailinglist/archive/2011/6/16/using-timestamps-to-prevent-session-hijacking/

That's the kind of thing I'm thinking of. Storing them somewhere is
useful (and I may end up doing that) but it does defeat client-side
sessions somewhat.

Overall, my point is, the functionality is already there to have a bit
more security, it just needs to be enabled. :)

Jacob

-- 
Jacob Peddicord
http://jacob.peddicord.net/

Re: [flask] Security of secure sessions

From:
Jacob Peddicord
Date:
2011-08-16 @ 01:04
Looking back on this, I apologize for my alarmist tone in my first few
messages. Having thought about it for some time and looking around, I
can see that I'm quite obviously not the first to think of this issue.
:)

For those looking to use a full login session, take a look at
Flask-Login[1], which does almost exactly what I was looking for and
then some. To look into more secure cookies at a lower level, see
itsdangerous[2] (sorry Armin, I didn't realize you were actually
referencing a Python package when you mentioned this).

Thank you all for your feedback, it was most helpful.

Cheers,
Jacob

[1] http://packages.python.org/Flask-Login/
[2] http://packages.python.org/itsdangerous/


-- 
Jacob Peddicord
http://jacob.peddicord.net/

Re: [flask] Security of secure sessions

From:
Daniele Nicolodi
Date:
2011-08-15 @ 13:57
On 15/08/11 15:35, Jacob Peddicord wrote:
> With server-side sessions, the session can easily be invalidated.
> That's not possible with secure cookies, so there needs to be a way
> for a cookie to invalidate itself. This is already done for permanent
> cookies: since they have an expiration, they will be invalid after a
> set amount of time, and the risk is confined.

Expiration date of permanent cookie is enforced on the client side,
AFAIK, so setting an expiration time is not a solution.

A bend aid, also embraced by other frameworks, is to rotate the secure
key used for cookies signing. That, however, is not trivial, because you
need to sign new cookies with the new key, but keep old keys in a pool,
for a given amount of time, and use those to validate incoming cookies,
so that legitimate session keep to valid when the key rotates.

Cheers,

PS: trying to plug all the holes that a careless user can leave into the
security of an application (web application especially) is a never
ending job. This time is much better spent teaching users to press the
logout button...

-- 
Daniele

Re: [flask] Security of secure sessions

From:
Jacob Peddicord
Date:
2011-08-15 @ 14:03
On Mon, Aug 15, 2011 at 9:57 AM, Daniele Nicolodi <daniele@grinta.net> wrote:
> Expiration date of permanent cookie is enforced on the client side,
> AFAIK, so setting an expiration time is not a solution.

On the surface this would seem to be the case, but Werkzeug actually
encodes and checks the expiration in the cookie data itself (with key
'_expires').

See: 
https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/contrib/securecookie.py#L228

-- 
Jacob Peddicord
http://jacob.peddicord.net/