Forum: Rails-core (closed, excessive spam) Replay attacks with cookie session

Posted by Robert James (robertjames)
on 2007-03-21 19:44
(Received via mailing list)
I'm concerned about the possibility of replay attacks with cookie
sessions.  This is a standard security issue.

Example:
1. User receives credits, stored in his session
2. User buys something
3. User gets his new, lower credits stored in his session
4. Evil hacker takes his saved cookie from step #1 and pastes it back
in his browser's cookie jar.  Now he's gotten his credits back.

This is normally solved using something called nonce - each signing
includes a once only code, and the signer keeps track of all of the
codes, and rejects any message with the code repeated.  But that's
very hard to do here, since there may be several app servers
(mongrels).

Of course, we could store the nonce in the DB - but that defeats the
entire purpose!
Posted by Jeremy Kemper (Guest)
on 2007-03-21 20:29
(Received via mailing list)
On 3/21/07, S. Robert James <srobertjames@gmail.com> wrote:
> I'm concerned about the possibility of replay attacks with cookie
> sessions.  This is a standard security issue.
>
> Example:
> 1. User receives credits, stored in his session
> 2. User buys something
> 3. User gets his new, lower credits stored in his session
> 4. Evil hacker takes his saved cookie from step #1 and pastes it back
> in his browser's cookie jar.  Now he's gotten his credits back.

Interesting, I hadn't considered that scenario.


> This is normally solved using something called nonce - each signing
> includes a once only code, and the signer keeps track of all of the
> codes, and rejects any message with the code repeated.  But that's
> very hard to do here, since there may be several app servers
> (mongrels).

This sounds like something you could perform at the application level.

jeremy
Posted by Brad Ediger (Guest)
on 2007-03-21 20:47
(Received via mailing list)
On Mar 21, 2007, at 1:43 PM, S. Robert James wrote:

>
> This is normally solved using something called nonce - each signing
> includes a once only code, and the signer keeps track of all of the
> codes, and rejects any message with the code repeated.  But that's
> very hard to do here, since there may be several app servers
> (mongrels).
>
> Of course, we could store the nonce in the DB - but that defeats the
> entire purpose!
>

You and I think alike. I was just considering this the other day as
well. The trivial fix is to say "don't store sensitive transient data
in the session". I think that leaves something to be desired, but it
is probably the preferred route unless there is a clean technical
solution.
Posted by Robert James (robertjames)
on 2007-03-21 21:57
(Received via mailing list)
On Mar 21, 3:28 pm, "Jeremy Kemper" <jer...@bitsweat.net> wrote:
> On 3/21/07, S. Robert James <srobertja...@gmail.com> wrote:
>
> > I'm concerned about the possibility of replay attacks with cookie
> > sessions.  This is a standard security issue.

> Interesting, I hadn't considered that scenario.

IMO, we need to rethink moving to cookie sessions by default, then -
if a core member hadn't thought about, what can we expect from
beginners? Last thing we need is a reputation for being weak in
security.

Before everyone responds: "It will help performance, and good
developers don't store volatile data in the session, anyway!" I'll say
that we've seen lots of companies (who won't be named) sacrifice
security in order to gain out of the box performance or ease of use -
and it comes back to haunt them.  Secure by default, and let the
advanced users make it less secure to improve performance - not the
other way around.

>
> > This is normally solved using something called nonce - each signing
> > includes a once only code, and the signer keeps track of all of the
> > codes, and rejects any message with the code repeated.

> This sounds like something you could perform at the application level.
I don't think so - as long as step 2 (in my example) goes to one
Mongrel, and step 4 goes to another, the attack succeeds.  I can try
repeatedly with a script until this happens.  The only way to protect
is to use a shared backend like the DB or DRB - but then you've lost
the point of cookie sessions.
Posted by Jeremy Kemper (Guest)
on 2007-03-21 22:37
(Received via mailing list)
On 3/21/07, S. Robert James <srobertjames@gmail.com> wrote:
> IMO, we need to rethink moving to cookie sessions by default, then -
> if a core member hadn't thought about, what can we expect from
> beginners? Last thing we need is a reputation for being weak in
> security.

I think that's a bit sensational.  The cookie store has gone through a
couple of evolutionary steps already and is ready for more, if need
be.


> Before everyone responds: "It will help performance, and good
> developers don't store volatile data in the session, anyway!" I'll say
> that we've seen lots of companies (who won't be named) sacrifice
> security in order to gain out of the box performance or ease of use -
> and it comes back to haunt them.  Secure by default, and let the
> advanced users make it less secure to improve performance - not the
> other way around.

Let's see a brainstorm of solutions and other potential vulnerabilities.


> > > This is normally solved using something called nonce - each signing
> > > includes a once only code, and the signer keeps track of all of the
> > > codes, and rejects any message with the code repeated.
>
> > This sounds like something you could perform at the application level.
> I don't think so - as long as step 2 (in my example) goes to one
> Mongrel, and step 4 goes to another, the attack succeeds.  I can try
> repeatedly with a script until this happens.  The only way to protect
> is to use a shared backend like the DB or DRB - but then you've lost
> the point of cookie sessions.

To some degree. I'm sure there's more to this, though. I'm not a crypto 
expert.

jeremy
Posted by Preston Lee (Guest)
on 2007-03-21 23:48
(Received via mailing list)
I'm neither a Rails nor cryptography expert, but the threat of
session hijacking is a very important issue, and due to compliance
requirements such as SOX, sites must think even more seriously about
what is being stored in sessions and cookies, and take reasonable
measures to protect them.. preferably by default.

I'm saddened that many recent Rails books don't seem to cover this
issue. If the problem had more clarity and direction I think that'd
go a long way to easing enterprises into the Rails community.

Preston
Posted by Sandofsky (Guest)
on 2007-03-22 00:33
(Received via mailing list)
I'm not a crypto person, but what if a version number were embedded
with every write to the cookie session? Of course, check the data
+version against a hash to make sure they didn't tinker with the
version.
Posted by Brad Ediger (Guest)
on 2007-03-22 00:47
(Received via mailing list)
That's essentially what a nonce is, but:

1) Nonce is random and can't easily be guessed
2) It still doesn't solve the multiserver problem: how does one
server know what the current version number is when there are 10
Mongrels?
Posted by Alexey Verkhovsky (Guest)
on 2007-03-22 06:18
(Received via mailing list)
On 3/21/07, Brad Ediger <brad@bradediger.com> wrote:
>
> You and I think alike. I was just considering this the other day as
> well. The trivial fix is to say "don't store sensitive transient data
> in the session".


Heh... how about a user ID? What if an evil hacker sets it to 1, 
assuming
that the first user is likely to be admin?

Alex
Posted by Brad Ediger (Guest)
on 2007-03-22 06:25
(Received via mailing list)
On Mar 22, 2007, at 12:16 AM, Alexey Verkhovsky wrote:

> On 3/21/07, Brad Ediger <brad@bradediger.com> wrote:
> You and I think alike. I was just considering this the other day as
> well. The trivial fix is to say "don't store sensitive transient data
> in the session".
>
> Heh... how about a user ID? What if an evil hacker sets it to 1,  
> assuming that the first user is likely to be admin?
>

He can't, the HMAC wouldn't verify.
Posted by Alexey Verkhovsky (Guest)
on 2007-03-22 06:57
(Received via mailing list)
On 3/21/07, Brad Ediger <brad@bradediger.com> wrote:
>
> Heh... how about a user ID? What if an evil hacker sets it to 1, assuming
> that the first user is likely to be admin?
>



He can't, the HMAC wouldn't verify.
>

Ah, that's right. So the only possible attack vector here is copying the
entire cookie, including HMAC?

OK, how about making this option available, but not default? And 
documenting
explicitly that if you switch to this option, you should be extremely
cautious about putting what you called "sensitive transient data" in the
session? This looks like a good compromise, because people with a clue 
would
still use it (for both maintainability and performance benefits) while
people without a clue will have to figure it out, and hopefully read the
warning in the docs.

Personally, I'd much rather deal with beginners having "Rails 
performance
sucks" pains early on (because of file-based sessions), rather than
discovering that "Rails security is totally screwed" a year after
production.

Alex
Posted by Manfred Stienstra (Guest)
on 2007-03-22 08:28
(Received via mailing list)
On Mar 21, 2007, at 11:08 PM, Preston Lee wrote:

> I'm neither a Rails nor cryptography expert, but the threat of   
> session hijacking is a very important issue

It's an important issue when you're trying to have a secure session.
When you're just using the session for some flash variables I don't
see the point in using an overly secure session system.

I think we should document the various session stores very well and
tell people what to use in which circumstances.

Developers aren't small children, we don't have to make their
decisions for them.

Manfred
Posted by Thijs van der Vossen (Guest)
on 2007-03-22 09:35
(Received via mailing list)
On Mar 21, 2007, at 19:43, S. Robert James wrote:

>
> >
--
Fingertips - http://www.fngtps.com

Phone: +31 (0)6 24204845
Skype: tvandervossen

MSN Messenger: thijs@fngtps.com
iChat/AOL:  t.vandervossen@mac.com
Jabber IM: thijs@jabber.org
Posted by Thijs van der Vossen (Guest)
on 2007-03-22 09:46
(Received via mailing list)
On Mar 21, 2007, at 19:43, S. Robert James wrote:
> I'm concerned about the possibility of replay attacks with cookie  
> sessions.  This is a standard security issue.
>
> Example:
> 1. User receives credits, stored in his session
> 2. User buys something
> 3. User gets his new, lower credits stored in his session

Your example scenario is unrealistic. If you really think it's a good
idea to store such important stuff as your user's credit in a session
instead of in your database you probably have bigger issues to worry
about. :)

As long as you only use the session to maintain the id of the
authenticated user and for flash messages there's absolutely nothing
to worry about.

Kind regards,
Thijs

P.S. If you really _do_ think it's a good idea to store your user's
credit in the session, please google for 'share-nothing' and
'database transactions' and do some reading.

--
Fingertips - http://www.fngtps.com

Phone: +31 (0)6 24204845
Skype: tvandervossen

MSN Messenger: thijs@fngtps.com
iChat/AOL:  t.vandervossen@mac.com
Jabber IM: thijs@jabber.org
Posted by Alexey Verkhovsky (Guest)
on 2007-03-22 14:53
(Received via mailing list)
On 3/22/07, Thijs van der Vossen <t.vandervossen@gmail.com> wrote:
>
> As long as you only use the session to maintain the id of the
> authenticated user and for flash messages there's absolutely nothing
> to worry about.
>

Sure, but...

Not everybody who develops web apps knows about "do not keep anything
interesting in sessions" mantra, or agrees with it. At least a couple of
times I had to explain it to people who were not clueless by any 
standard.

It's actually a rather arcane bit of knowledge, and if you don't have 
it,
you may discover it the hard way, when it's too late.

Which makes session storage in cookies a good option, but perhaps not a 
good
default (?)

Alex
Posted by Brad Ediger (Guest)
on 2007-03-22 15:46
(Received via mailing list)
On Mar 22, 2007, at 8:52 AM, Alexey Verkhovsky wrote:

> clueless by any standard.
>
> It's actually a rather arcane bit of knowledge, and if you don't  
> have it, you may discover it the hard way, when it's too late.
>
> Which makes session storage in cookies a good option, but perhaps  
> not a good default (?)
>

For those just tuning in... :-)

This is the crux of the issue... of *course* it's a terrible idea to
store sensitive or transient data in the session, but the question is
one of API design. Do we want the penalty for ignoring best practices
to be compromised security?

I happen to think it's not a huge deal if we document properly. Web
developers need to understand all of the abstractions that Rails
builds on top of HTTP in order to build a secure web app. It's the
same issue as people who throw things like

<input type="hidden" name="order[total_price]" value="1250.00" />

into their online stores. If you don't understand how the Web works,
you won't build secure applications, no matter what framework you
work within. When PStore was the default, professional developers
understood what that meant and what freedoms and limitations it
afforded us. Now that CookieStore is the default session store, we
are responsible for understanding what that means.

Don't get me wrong; the Rails team has a part to play in this --
documentation. To the extent that we give the impression that the
session is  a "big hash in the sky", people will put stupid things in
it.

After writing this and thinking about it, I realize that
authentication may be a problem. It makes me slightly uncomfortable
to hand the client a token saying, in effect, "I am logged in as Joe
User" with no qualifications, signed by the server. And that token
never expires on the server side -- you could come back 5 years later
and prove your identity. There is no way to selectively expire
sessions, e.g. based on time. You can change the secret, but that
expires all sessions including current ones. You can send the client
a new cookie that invalidates the old one -- but he can always ignore
it. He still has the valid authentication cookie from earlier, and it
will still work.

I would feel a lot better about it if it incorporated a nonce or some
other form of time-variant information. I can't come up with an
attack other than the replay attack, but that "I am logged in as Joe
User" message seems too general to make me feel completely
comfortable about authentication via cookie sessions for the time being.

Brad
Posted by Robert James (robertjames)
on 2007-03-22 17:20
(Received via mailing list)
On Mar 22, 10:44 am, Brad Ediger <b...@bradediger.com> wrote:
> This is the crux of the issue... of *course* it's a terrible idea to  
> store sensitive or transient data in the session, but the question is  
> one of API design. Do we want the penalty for ignoring best practices  
> to be compromised security?

It's even more complicated.  Defining "sensitive or transient data" is
not at all trivial.

The standard use case for a cookie session is store only flash and
user id.  Not sensitive or transient?  Okay.

Now, I click "Log Out", and get up from the library's computer, only
to let the person waiting after me to retrieve the old cookie.... That
innocuous user id just became both sensitive and transient.

The point is, answering these questions is hard.  Witness the
confusion in this thread alone.  DIY cryptosystems are hard:
professionals fail.  WEP failed.  Does it make sense to push all these
questions onto each new Rails developer's shoulders?
Posted by Brad Ediger (Guest)
on 2007-03-22 17:30
(Received via mailing list)
On Mar 22, 2007, at 11:15 AM, S. Robert James wrote:

> user id.  Not sensitive or transient?  Okay.
>
> Now, I click "Log Out", and get up from the library's computer, only
> to let the person waiting after me to retrieve the old cookie.... That
> innocuous user id just became both sensitive and transient.
>
> The point is, answering these questions is hard.  Witness the
> confusion in this thread alone.  DIY cryptosystems are hard:
> professionals fail.  WEP failed.  Does it make sense to push all these
> questions onto each new Rails developer's shoulders?

And I think that is exactly what it comes to. That's kind of where I
landed with that post when I started considering what user_id really
meant.

As neat as cookie sessions are, I don't think I'm going to use them
to store authentication info anymore. Too many question marks.
Posted by Steve Longdo (Guest)
on 2007-03-22 19:10
(Received via mailing list)
This problem can be addressed in a lot of ways.  One of the easiest
approaches would be to use a filter to process the validity of a cookie.
Have an after_filter that adds a "single-use" token to the cookie after 
a
request and a before_filter that checks for the "single-use" token when 
a
user makes a new request.  That way a replay attack wouldn't work.

Bundling in something like this into Rails makes a lot of sense.  It 
would
be opt in by adding the filters into application.rb and not forced on 
anyone
by default.

On 3/22/07, Brad Ediger <brad@bradediger.com> wrote:
> > It's even more complicated.  Defining "sensitive or transient data" is
> > confusion in this thread alone.  DIY cryptosystems are hard:
>
> >
>


--
Thanks,
-Steve
http://www.stevelongdo.com
Posted by Brad Ediger (Guest)
on 2007-03-22 19:25
(Received via mailing list)
This was discussed earlier in the thread. The problem is that such a
nonce would require communication between the backend servers via DRb
or the database, which removes any benefit from storing the cookies
client-side. You might as well store the whole session in the
database or DRb store.

As for the opt-in, if you're the type of user that would know enough
about security to opt in to such a plan, you're probably not storing
account balances in a client-side cookie. The discussion we are
having concerns sensible defaults.
Posted by Alexey Verkhovsky (Guest)
on 2007-03-22 19:27
(Received via mailing list)
On 3/22/07, Steve Longdo <steve.longdo@gmail.com> wrote:
>
> Have an after_filter that adds a "single-use" token to the cookie after a
> request and a before_filter that checks for the "single-use" token when a
> user makes a new request.


1. I probably misunderstand your point, because I'm about to say 
something
obvious. Requests that belong to the same session are not guaranteed to 
be
sequential in any meaningful way.

2. The check you are talking about would have to check the session 
against
SOMETHING. Something more specific than a single secret. I.e., a piece 
of
server-side data that maps to the session. Which kills the rationale 
behind
session-based cookies, no?

So, it looks like cookie-based sessions would only work for the same
scenarios where "Remember my login on this computer" option without an 
opt
out is acceptable.

Alex
Posted by Courtenay (Guest)
on 2007-03-22 19:54
(Received via mailing list)
On 3/22/07, S. Robert James <srobertjames@gmail.com> wrote:
> On Mar 22, 10:44 am, Brad Ediger <b...@bradediger.com> wrote:
> Now, I click "Log Out", and get up from the library's computer, only
> to let the person waiting after me to retrieve the old cookie.... That
> innocuous user id just became both sensitive and transient.

You click 'log out' and it deletes the cookie.
This is no different to a normal server-based session.

court3nay
Posted by Brad Ediger (Guest)
on 2007-03-22 20:01
(Received via mailing list)
On Mar 22, 2007, at 1:53 PM, Courtenay wrote:

>
> On 3/22/07, S. Robert James <srobertjames@gmail.com> wrote:
>> On Mar 22, 10:44 am, Brad Ediger <b...@bradediger.com> wrote:
>> Now, I click "Log Out", and get up from the library's computer, only
>> to let the person waiting after me to retrieve the old cookie....  
>> That
>> innocuous user id just became both sensitive and transient.
>
> You click 'log out' and it deletes the cookie.
> This is no different to a normal server-based session.

Oh, but it is. With a server-based session, I "Log Out" and my
session can be purged from the server, leaving the old session ID
worthless. With cookie sessions, the cookie is still valid to the
server even if deleted from the browser's cookie repo. There is no
way to selectively expire sessions from the server.

Server-side: someone gets my session ID, I log out, they present the
session ID to the server -> worthless.
Client-side: someone gets my session cookie, I log out, they present
the cookie to the server -> impersonation!
Posted by Patrick Ritchie (Guest)
on 2007-03-22 20:01
(Received via mailing list)
Courtenay wrote:
>   
Actually, if you have the cookie set to expire at the end of the
session, simply closing your web browser should delete the cookie.

Cheers!
Patrick
Posted by Jeremy Evans (Guest)
on 2007-03-22 20:22
(Received via mailing list)
On 3/22/07, Brad Ediger <brad@bradediger.com> wrote:
> >
> session ID to the server -> worthless.
> Client-side: someone gets my session cookie, I log out, they present
> the cookie to the server -> impersonation!

It's possible mitigate the problem somewhat by having an expiration
time put into the session (which cannot be modified by an attacker due
to the HMAC).  However, you still won't be able to manually expire
sessions (i.e. log out).

Jeremy
Posted by Brad Ediger (Guest)
on 2007-03-22 20:30
(Received via mailing list)
On Mar 22, 2007, at 2:21 PM, Jeremy Evans wrote:

>>>> to let the person waiting after me to retrieve the old cookie....
>> way to selectively expire sessions from the server.
>>
>> Server-side: someone gets my session ID, I log out, they present the
>> session ID to the server -> worthless.
>> Client-side: someone gets my session cookie, I log out, they present
>> the cookie to the server -> impersonation!
>
> It's possible mitigate the problem somewhat by having an expiration
> time put into the session (which cannot be modified by an attacker due
> to the HMAC).  However, you still won't be able to manually expire
> sessions (i.e. log out).

This is the best idea I've seen so far, but it still requires
balancing the attack window (as small as possible) against the
maximum allowed time between requests. Given that replay attacks can
be automated, the acceptable values for these numbers may or may not
overlap, depending on the application.
Posted by Courtenay (Guest)
on 2007-03-22 20:54
(Received via mailing list)
On 3/22/07, Brad Ediger <brad@bradediger.com> wrote:
> to store authentication info anymore. Too many question marks.
You're forgetting that:
    (a) sessions already use cookies to store the session ID, so any
issues with cookie interception or other attacks apply to all session
storage methods.
    (b) you can't change the contents of the cookie or it will fail the 
HMAC.

If you're overly concerned with "user_id" haxoring, just use a guid
instead of DB id in your User.find

court3nay
Posted by Robert James (robertjames)
on 2007-03-22 21:52
(Received via mailing list)
On Mar 22, 3:08 pm, Courtenay <court3...@gmail.com> wrote:
> You're forgetting that:
>     (a) sessions already use cookies to store the session ID, so any
> issues with cookie interception or other attacks apply to all session
> storage methods.

Not true.  Example: if, on logout, you update the session in the DB to
state "No User", the cookie is worthless.

>     (b) you can't change the contents of the cookie or it will fail the HMAC.

Yes, but you can replay them.  See my first post.

> If you're overly concerned with "user_id" haxoring, just use a guid
> instead of DB id in your User.find

Won't help - see earlier posts.
Posted by Robert James (robertjames)
on 2007-03-22 22:15
(Received via mailing list)
On Mar 22, 3:21 pm, "Jeremy Evans" <jeremyeva...@gmail.com> wrote:
> It's possible mitigate the problem somewhat by having an expiration
> time put into the session (which cannot be modified by an attacker due
> to the HMAC).  However, you still won't be able to manually expire
> sessions (i.e. log out).

This will only help in cases where the attacker wants to steal
someone's identity.  But there are other uses of a replay attack -
like the example I initially mentioned - where this won't help at
all.  And even in the identity theft case - what's to stop the
attacker from using the computer 5 minutes after I leave?

In general, I'd offer the amount of confusion on this thread as the
best evidence that the average developer shouldn't have to deal with
these issues by default.
Posted by Jeremy Kemper (Guest)
on 2007-03-23 01:28
(Received via mailing list)
On 3/22/07, Brad Ediger <brad@bradediger.com> wrote:
> This was discussed earlier in the thread. The problem is that such a nonce
> would require communication between the backend servers via DRb or the
> database, which removes any benefit from storing the cookies client-side.
> You might as well store the whole session in the database or DRb store.

Avoiding a single database lookup isn't the purpose of the cookie store.


> As for the opt-in, if you're the type of user that would know enough about
> security to opt in to such a plan, you're probably not storing account
> balances in a client-side cookie. The discussion we are having concerns
> sensible defaults.

This discussion skipped plugging the session replay hole. I understand
your concern, but I think you underestimate the average Rails
developer.

For example: to prevent user_id replay, store a last access timestamp
in session that's updated on login and logout.

jeremy
Posted by Daniel ----- (liquid)
on 2007-03-23 01:45
(Received via mailing list)
On 3/23/07, Courtenay <court3nay@gmail.com> wrote:
>
>
>
>     (b) you can't change the contents of the cookie or it will fail the
> HMAC.
>
> If you're overly concerned with "user_id" haxoring, just use a guid
> instead of DB id in your User.find
>
> court3nay


So does this mean that I can't use the cookie for client side 
javascript?
If I want to use it to keep track of some client side script, then I
can't?   Is that true?

Cheers
Posted by Michael Koziarski (Guest)
on 2007-03-23 01:46
(Received via mailing list)
> Avoiding a single database lookup isn't the purpose of the cookie store.

It's worth remembering the downsides to our current default.
Deploying to a 'real' production setup with it is a shortcut to a
heart attack.  File locking, mongrel deadlocking, NFS churn.   All of
those are real problems which hurt developers every day.

That most applications *already* change their session store indicates
that it's not that big a deal.  If you're currently doing something
which is incompatible with the assumptions of the cookie store,
switch.  I'm still using sql sessions and intend to continue doing so
:).


--
Cheers

Koz
Posted by Brad Ediger (Guest)
on 2007-03-23 01:52
(Received via mailing list)
On Mar 22, 2007, at 7:27 PM, Jeremy Kemper wrote:

>
> Avoiding a single database lookup isn't the purpose of the cookie  
> store.

Sure, but you do remove a lot of the glamour of the cookie store if
it has to be tied to a database for a nonce lookup anyway.

> developer.
I might be over-concerned here, but I'm not talking about the average
Rails developer. I'm talking about the worst ones. I can tell you
that while the average Rails developer I've worked with would
certainly be able to understand this and work around it, I'm not sure
that the worst ones would even understand what the issue was if it
were explained to them.

> For example: to prevent user_id replay, store a last access timestamp
> in session that's updated on login and logout.

If I understand you correctly, you would also keep a copy of the
latest timestamp server-side. I would submit that for many
developers, storing a timestamp for each session on the server is not
much more attractive than just storing the whole session on the server.

be
Posted by Brad Ediger (Guest)
on 2007-03-23 02:03
(Received via mailing list)
On Mar 22, 2007, at 7:43 PM, Daniel N wrote:

>
> court3nay
>
> So does this mean that I can't use the cookie for client side  
> javascript?  If I want to use it to keep track of some client side  
> script, then I can't?   Is that true?
>

Nope. Cookies are referenced by name. As long as you don't try to use
the same name for your session cookie and your client-side JS, you
will be fine.

be
Posted by Brad Ediger (Guest)
on 2007-03-23 02:05
(Received via mailing list)
On Mar 22, 2007, at 7:46 PM, Michael Koziarski wrote:

> that it's not that big a deal.  If you're currently doing something
> which is incompatible with the assumptions of the cookie store,
> switch.  I'm still using sql sessions and intend to continue doing so
> :).

This is a good point. The CookieStore is a major improvement over
PStore from a functional perspective. We are arguing over things that
are important to discuss, but still very, very small compared to that.
Posted by Robert James (robertjames)
on 2007-03-23 03:31
(Received via mailing list)
On Mar 22, 8:27 pm, "Jeremy Kemper" <jer...@bitsweat.net> wrote:
> For example: to prevent user_id replay, store a last access timestamp
> in session that's updated on login and logout.

Store the last access *where*?

In Mongrel? But only one Mongrel can know that without them talking to
each other.
In the DB? So we need to hit the DB each time, only we need to do it
manually?
In a temp file? That's back to the default session store.
In the cookie itself? We haven't solved the problem.  If the attacker
fishes out an older cookie - and, believe me, they're still on the
disk - he does a replay attack.

I think this is a fair question: most of the people arguing that
cookie stores are safe have also pointed out that they're not crypto
experts.  Or security experts.  Which is fine - I'm sure their top
notch developers.  Before making something which relies on crypto the
Rails default, doesn't it make sense to have at least _one_ crypto or
security consultant review it? Perhaps Schneier will take a look...

SRJ, over-and-out
Posted by Michael Koziarski (Guest)
on 2007-03-23 04:42
(Received via mailing list)
> I think this is a fair question: most of the people arguing that
> cookie stores are safe have also pointed out that they're not crypto
> experts.  Or security experts.  Which is fine - I'm sure their top
> notch developers.  Before making something which relies on crypto the
> Rails default, doesn't it make sense to have at least _one_ crypto or
> security consultant review it? Perhaps Schneier will take a look...

If you'd like to coordinate this, I'd definitely be glad to hear from
them.  As it stands I think your complaint boils down to the lack of
server-side invalidation of a session.  Most everything else flows
from that.  I'm not sure that there's a shared nothing way to take
care of that, but the crypto experts would know for sure.

Please do investigate having someone conduct a review.

--
Cheers

Koz
Posted by Luca Mearelli (Guest)
on 2007-03-23 09:29
(Received via mailing list)
Michael Koziarski wrote:
> That most applications *already* change their session store indicates
> that it's not that big a deal.  

My feeling (this is what I did) is that this happens because they *got
bitten* by the default session store problems, the effects are visible
(mainly the performance issues).

> If you're currently doing something
> which is incompatible with the assumptions of the cookie store,
> switch.  
this could be solved by clearly documenting this assumptions (and
perhaps giving suggestions)

> I'm still using sql sessions and intend to continue doing so
> :).
hmm... how about defaulting to these (at least for the production
environment)?

Luca
--

Web:   http://spazidigitali.com - http://thetyper.com
Email mailto://luca.mearelli@gmail.com
Skype callto://l.mearelli
--
Posted by Sandofsky (Guest)
on 2007-03-23 09:31
(Received via mailing list)
Pulling two IDs (session id + nonce) from the DB is better than
pulling 80k that could go in cookies. Why not include nonce in the
default, and if the developer wants the blazing speed (and
corresponding dangers), they can disable it?
Posted by Brad Ediger (Guest)
on 2007-03-23 15:39
(Received via mailing list)
On Mar 23, 2007, at 3:30 AM, Sandofsky wrote:

>
> Pulling two IDs (session id + nonce) from the DB is better than
> pulling 80k that could go in cookies. Why not include nonce in the
> default, and if the developer wants the blazing speed (and
> corresponding dangers), they can disable it?

80k cannot go in cookies. On most platforms the limit is 4k. The
CookieStore raises an error if you try to store too much.

And it's a difference between grabbing the data from the DB to
deserialize it and grabbing it from a cookie to deserialize it. The
main driver isn't performance -- it's not having to keep all of those
sessions around on the web server.
Posted by Jeremy Kemper (Guest)
on 2007-03-23 16:32
(Received via mailing list)
On 3/22/07, Brad Ediger <brad@bradediger.com> wrote:
> On Mar 22, 2007, at 7:27 PM, Jeremy Kemper wrote:
> > Avoiding a single database lookup isn't the purpose of the cookie
> > store.
>
> Sure, but you do remove a lot of the glamour of the cookie store if
> it has to be tied to a database for a nonce lookup anyway.

Smudge her mascara a little; she's still sexy in the morning.

I already User.find(session[:user_id]) per request, so perhaps my
expectations are different from yours.


> > This discussion skipped plugging the session replay hole. I understand
> > your concern, but I think you underestimate the average Rails
> > developer.
>
> I might be over-concerned here, but I'm not talking about the average
> Rails developer. I'm talking about the worst ones. I can tell you
> that while the average Rails developer I've worked with would
> certainly be able to understand this and work around it, I'm not sure
> that the worst ones would even understand what the issue was if it
> were explained to them.

I don't think you're over-concerned. However, attempts to find a
solution are not argument that session replay isn't a problem.


> > For example: to prevent user_id replay, store a last access timestamp
> > in session that's updated on login and logout.
>
> If I understand you correctly, you would also keep a copy of the
> latest timestamp server-side. I would submit that for many
> developers, storing a timestamp for each session on the server is not
> much more attractive than just storing the whole session on the server.

Let's talk about practical fixes rather than whether we should write
it off entirely.

An application-level solution to user_id replay:

  Per request:
    @current_user =
User.find_by_id_and_last_seen_at(session[:user_id],
session[:last_seen_at])

  On login:
    @current_user.update_attribute :last_seen_at, Time.now
    session[:user_id] = @current_user.id
    session[:last_seen_at] = @current_user.last_seen_at

  On logout:
    @current_user.update_attribute :last_seen_at, Time.now
    reset_session

This requires one additional database query on logout to invalidate
future reuse of that session and no additional per-request queries.

Anyone care to try a generic, automatic nonce and benchmark the results?

jeremy
Posted by Jeremy Evans (Guest)
on 2007-03-23 17:46
(Received via mailing list)
On 3/23/07, Jeremy Kemper <jeremy@bitsweat.net> wrote:
>   On login:
>     @current_user.update_attribute :last_seen_at, Time.now
>     session[:user_id] = @current_user.id
>     session[:last_seen_at] = @current_user.last_seen_at
>
>   On logout:
>     @current_user.update_attribute :last_seen_at, Time.now
>     reset_session
>
> This requires one additional database query on logout to invalidate
> future reuse of that session and no additional per-request queries.

This assumes you are doing a query per request anyway, and basically
piggy backing on it for the security.  If your application is already
doing a query for the current user for every request, sure, there's
almost no additional cost.  However, if your application isn't doing a
query per request, you have to add one to get the security, which
makes the cost the same as using the database for session storage.

IMO, this is not a problem that the application developer should need
to deal with manually, any more than application developers should
handle database transactions manually.  If cookie based session
storage is going to remain the default:

1) There should be a configurable timeout set automatically, with a
reasonable default (to partially mitigate the replay issue)
2) It should be documented that replay attacks are still possible
3) Advice on creating application specific solutions such as the one
you mentioned should be included in the documentation

Note that timeouts provide only slight additional security, as they
only protect against attackers who get access to a session cookie
after it has already expired.  If an attacker gets access to any
session cookie before it expires, they can keep that session open
indefinitely.

Jeremy
Posted by Brad Ediger (Guest)
on 2007-03-23 17:53
(Received via mailing list)
Good points. I worked up a quick plugin that uses DRb to store the
nonce, and I'm doing some benchmarks on it now. I don't have time for
anything fancy, but we can at least get in the ballpark.

Or, to put it in Zed's terms, we'll just run it 100 times each way
and compare the numbers. :-)

<ducks>
Posted by Brad Ediger (Guest)
on 2007-03-23 18:30
(Received via mailing list)
OK, here it is: svn://svn.madriska.com/plugins/raisin_cookies

To use, install the plugin and start up the DRb server from the DRb
session store (action_controller/session/drb_server.rb).

The DRb server keeps a hash mapping session HMACs to the latest nonce
used with the session. The nonce is verified along with the HMAC on
unmarshal. That way, old sessions are invalidated because the HMAC of
the session must be presented with the latest nonce stored in the DRb
backend.

Right now, the code issues a new nonce on each update; it should
probably check first to see if the data has been updated, but it
doesn't right now.

Very simple benchmarking shows a 10-15% impact on reqs/sec with this
plugin. I would guess that most of that comes from the nonce
generation (I use Rails's CGI::Session.generate_unique_id, which has
to create an MD5 hash for each session). I don't really have the time
to look further, however. I only tested with a single Mongrel. Does
anyone care to do some performance studies on this?

Brad

On Mar 23, 2007, at 11:52 AM, Brad Ediger wrote:

> Good points. I worked up a quick plugin that uses DRb to store the  
> nonce, and I'm doing some benchmarks on it now. I don't have time  
> for anything fancy, but we can at least get in the ballpark.
>
<snip>
Posted by Jeremy Kemper (Guest)
on 2007-03-23 19:19
(Received via mailing list)
On 3/23/07, Jeremy Evans <jeremyevans0@gmail.com> wrote:
> On 3/23/07, Jeremy Kemper <jeremy@bitsweat.net> wrote:
> > Let's talk about practical fixes rather than whether we should write
> > it off entirely.

...


> > This requires one additional database query on logout to invalidate
> > future reuse of that session and no additional per-request queries.
>
> This assumes you are doing a query per request anyway, and basically
> piggy backing on it for the security.  If your application is already
> doing a query for the current user for every request, sure, there's
> almost no additional cost.  However, if your application isn't doing a
> query per request, you have to add one to get the security, which
> makes the cost the same as using the database for session storage.

That assumption is stated at the beginning of the example:
> > An application-level solution to user_id replay:

You reason that touching the database "makes the cost the same as
using the database for session storage" which is likely wrong and
certainly unsubstantiated.

Criticism is great and welcome, everyone, but let's add some
creativity and code to the mix, please.


> IMO, this is not a problem that the application developer should need
> to deal with manually, any more than application developers should
> handle database transactions manually.  If cookie based session
> storage is going to remain the default:

We all agree on this. We're working on it.


> 1) There should be a configurable timeout set automatically, with a
> reasonable default (to partially mitigate the replay issue)
> 2) It should be documented that replay attacks are still possible
> 3) Advice on creating application specific solutions such as the one
> you mentioned should be included in the documentation

Good ideas.


> Note that timeouts provide only slight additional security, as they
> only protect against attackers who get access to a session cookie
> after it has already expired.  If an attacker gets access to any
> session cookie before it expires, they can keep that session open
> indefinitely.

Not in the scenario above: the legitimate user logging out invalidates
the attacker's session, which is the same behavior as a server-side
session.

jeremy
Posted by Sandofsky (Guest)
on 2007-03-23 19:37
(Received via mailing list)
> 80k cannot go in cookies. On most platforms the limit is 4k. The
> CookieStore raises an error if you try to store too much.

http://tools.ietf.org/html/rfc2109

"at least 4096 bytes per cookie ... at least 20 cookies per unique
host or domain name"

Is there something in today's cookie implementation that prevents
someone from doing 20 cookies at 4k each?
Posted by Brad Ediger (Guest)
on 2007-03-23 19:45
(Received via mailing list)
On Mar 23, 2007, at 1:35 PM, Sandofsky wrote:

> someone from doing 20 cookies at 4k each?
I defer to my original statement:

>> The CookieStore raises an error if you try to store too much.

There is a hard-coded 4k limitation in the store, and the store will
only use one cookie per session.
Posted by Robert James (robertjames)
on 2007-03-23 22:47
(Received via mailing list)
On Mar 22, 11:42 pm, "Michael Koziarski" <mich...@koziarski.com>
wrote:
> If you'd like to coordinate this, I'd definitely be glad to hear from
> them....I'm not sure that there's a shared nothing way to take
> care of that, but the crypto experts would know for sure.
>
> Please do investigate having someone conduct a review.

Will do - I'll speak to some of my contacts and see if they're willing
to do a short review, pro bono.

> I'm not sure that there's a shared nothing way to take
> care of that
Exactly.  Basically, you can mathematically prove that the only way to
avoid replay attacks is with some type of trusted store.  Which of
course needs to be shared.

@Brad - Great work on setting up some code for benchmarking.  I
haven't reviewed your code,  but doing nonces correctly gets into some
sticky synchronization and concurrency.  Basically, the system needs
to make sure that:

* The nonces used by all of the Mongrels are kept track of (eg one
counter per Mongrel)

* No Mongrel uses the same nonce (eg prefix the nonce with the
Mongrel's pid)

* That the issuing a nonce, restoring a session, and then invalidating
the nonce are all done in the correct order.  This can get very
tricky:

Specifically, we need to make sure that once the session has been
modified, its nonce is invalidated immediately.  At the same time, we
can't invalidate it before a new session has been assigned, or those
requests will be incorrectly rejected.  This gets very, very tricky
when you're dealing with multiple overlapping requests: invalidate too
soon, and you've broken pipelining.  Invalidate too late, and you're
subject to replay attacks.  Like I said, crypto is hard: amateur
cryptosystems are usually broken with relish.

@Jeremy - you're raising a good issue.  I think it would be beneficial
to define exactly what the goals of cookie sessions are.  Performance?
Less administrative setup? Simplicity (I think that's been lost
already)?  Not having to store dormant sessions? I'll add that, IMO,
an attraction to coolness and clever code is *not* a goal worth
pursuing.
Posted by Robert James (robertjames)
on 2007-03-23 23:01
(Received via mailing list)
On Mar 22, 11:42 pm, "Michael Koziarski" <mich...@koziarski.com>
wrote:
> If you'd like to coordinate this, I'd definitely be glad to hear from
> them.  As it stands I think your complaint boils down to the lack of
> server-side invalidation of a session.  Most everything else flows
> from that.  I'm not sure that there's a shared nothing way to take
> care of that, but the crypto experts would know for sure.
>
> Please do investigate having someone conduct a review.

To get started, here's a good link on the concept of replay attacks
and nonces:
http://www.openidenabled.com/openid/replay-attack-prevention

And here's a nonce implementation by Sam Ruby (not a crypto expert by
any means, but a smart Ruby dev for sure - the implementation is in
Python, though):
http://www.intertwingly.net/blog/1585.html
Posted by Brad Ediger (Guest)
on 2007-03-23 23:06
(Received via mailing list)
On Mar 23, 2007, at 4:47 PM, S. Robert James wrote:

>
> * That the issuing a nonce, restoring a session, and then invalidating
> the nonce are all done in the correct order.  This can get very
> tricky

Don't use that code. I had the wrong approach about this, and just
saw my mistake. We will need to rethink the approach, probably after
review from an expert. I'll be thinking about this in the meantime,
and I'll try to at least think a little next time before I start coding.
Posted by Sam Bravard (Guest)
on 2007-03-24 17:56
(Received via mailing list)
This is a basic distributed systems problem.  There is no way to do a
secure shared nothing approach on the client side without creating
server side tracking/coordination overhead.  I know cookie sessions
look simple and appealing at first but we're trading scalable
simplicity (db store), for complexity. For security and reliability
some sort of token (timestamps or nonces) would have to be coordinated
across all server instances and it needs to be perfectly coordinated
to work effectively.

http://www.cs.vu.nl/~ast/books/ds1/toc.html  (chapters 5, 6, and 8 are
good backgrounders)

The downsides of the cookie approach:

*) It causes more lookups/coordination overhead on the server side.
You still need a db or distributed transaction coordinator lookup
(each server in a cluster needs to know some sort of cluster protocol
for token or timestamp management), so we're not saving a db lookup
and have to maintain coordinator and recovery logic.
*) It puts state unencrypted in a client device we have no control
over (open to attack, reduces the usefulness of the store if we can't
put anything we want in there and feel safe about it)
*) It puts state in an unreliable device (browsers crash - especially
firefox with a few add-ons ;) that would require recovery logic

What is so broken that requires all of this messy overhead and
limitations?

In my mind there needs to be an overwhelming pain to justify the cost
and I can't see/feel the pain to justify this effort and wasted time
on the core list.

SamB
Posted by Wayne E. Seguin (Guest)
on 2007-03-24 22:42
(Received via mailing list)
I have a question on this discussion.

Would using Ajax requests throw a wrench into the works?

The example I'm thinking of is:

1. Request 1 hits the server invalidating the nonce for the session,
and runs for a bit

2. Request 2 comes in and gets rejected, hence the request fails and
something expected to happen doesn't

3. Request 1 completes and a new session cookie is set so that the
next action completes successfully.

Thanks,

   ~Wayne
Posted by Thijs van der Vossen (Guest)
on 2007-03-25 08:02
(Received via mailing list)
On Mar 23, 2007, at 1:51, Brad Ediger wrote:
> I might be over-concerned here, but I'm not talking about the average
> Rails developer. I'm talking about the worst ones. I can tell you
> that while the average Rails developer I've worked with would
> certainly be able to understand this and work around it, I'm not sure
> that the worst ones would even understand what the issue was if it
> were explained to them.

So you actually want to start designing the framework for its _worst_
users? :)

Kind regards,
Thijs

--
Fingertips - http://www.fngtps.com

Phone: +31 (0)6 24204845
Skype: tvandervossen

MSN Messenger: thijs@fngtps.com
iChat/AOL:  t.vandervossen@mac.com
Jabber IM: thijs@jabber.org
Posted by Brad Ediger (Guest)
on 2007-03-25 14:42
(Received via mailing list)
On Mar 25, 2007, at 1:01 AM, Thijs van der Vossen wrote:

> users? :)
From a security standpoint, absolutely. Certainly there is some
responsibility on the developer's part to learn how the web works,
but the framework should be as forgiving as possible to new users.

--be
Posted by Andreas Schwarz (Guest)
on 2007-03-25 18:53
(Received via mailing list)
On 24 Mrz., 18:55, "Sam Bravard" <sam.brav...@gmail.com> wrote:
> What is so broken that requires all of this messy overhead and limitations?

I agree with your view. Storing session data in cookies is a bad idea,
even if correctly implemented with a nonce. But the current
implementation in Rails is just outright dangerous and should be
removed.

Andreas
Posted by Robert James (robertjames)
on 2007-03-25 23:13
(Received via mailing list)
On Mar 25, 12:52 pm, "Andreas Schwarz" <goo...@andreas-s.net> wrote:
> On 24 Mrz., 18:55, "Sam Bravard" <sam.brav...@gmail.com> wrote:
>
> > What is so broken that requires all of this messy overhead and limitations?
>
> I agree with your view. Storing session data in cookies is a bad idea,
> even if correctly implemented with a nonce. But the current
> implementation in Rails is just outright dangerous and should be
> removed.

Here, here!

I did some more work over the weekend and have come up with some other
serious problems, which I want to discuss after I've looked into them
more.

Koz asked me to try to get a professional review done.  To do this, I
need two things (preferably
from core):

1. A short but precise spec on how the cookie sessions work. The
people doing the review may never have seen a line of Ruby in their
lives.  The spec should be specific and technical, just not assume
knowledge of Ruby.  It should also be brief, if we want anyone to go
over it pro bono.

2. A sample app, with src code and full configuration.  It can be
simple or even trivial, but it should show how the cookie session is
designed to be deployed.  But it has to follow the type of use that
would be recommended - nothing like "in real life, of course, we'd do
it in a more secure way".  The configuration and the like are just as
important as the app src.
Posted by Brad Ediger (Guest)
on 2007-03-26 00:11
(Received via mailing list)
On Mar 25, 2007, at 4:12 PM, S. Robert James wrote:

> Koz asked me to try to get a professional review done.  To do this, I
> need two things (preferably
> from core):
>
> 1. A short but precise spec on how the cookie sessions work. The
> people doing the review may never have seen a line of Ruby in their
> lives.  The spec should be specific and technical, just not assume
> knowledge of Ruby.  It should also be brief, if we want anyone to go
> over it pro bono.

I would be willing to draft a spec if the core team is too busy. We
could always run it by them for editing / approval.

be
Posted by Neil Wilson (neilw)
on 2007-03-26 20:28
(Received via mailing list)
Perhaps that is your problem. You haven't modelled the login session
properly in Rails.

There seems to be an assumption that 'session' handles all this
automatically, when in reality it is nothing more than a fancy hash.

A login session exists at a point in time for a particular period of
time. It should expire. It is related to a particular user ID (and
possibly a browser/IP sequence) and a particular set of transaction
sequences. You don't get that with 'session' - you have to model it
properly. If you haven't modelled the functionality, then you can't
expect to use it.

I suspect the name 'session' is the problem. It's an overloaded
concept with a load of built-in expectations. However
'semi_persistent_hash' isn't anywhere as easy to type.

NeilW
Posted by Neil Wilson (neilw)
on 2007-03-26 20:36
(Received via mailing list)
The 'standard' use is incorrect. I don't believe it has ever been put
forward as 'best practice' by any serious modeller. All I've seen it
in is in simplified tutorials. Are you sure it isn't a case of truth
by repeated assertion?

You shouldn't be storing ID references to the User model in the
session hash; you should be storing ID references to the
AuthenticatedSessions model.

That way when you click 'LogOut' the relevant AuthenticatedSession
object is deleted from the database, and then it doesn't matter one
jot what the next persion does with the cookie.

If something doesn't fit, then look to the model. You've probably
missed a relationship that should be a first class model object.
Posted by Brad Ediger (Guest)
on 2007-03-26 20:43
(Received via mailing list)
How, exactly, would you model the login session so as to be immune to
replay attacks with shared-nothing on the server side?

session[:user_id] is perfectly safe with a server-side session. It is
not with a client-side session.

User session expiration has almost nothing to do with this
discussion. Expiring user sessions doesn't prevent sessions from
being replayed during the validity period. And there's no way to
expire user sessions with only a client cookie. We're looking first
for a general solution.

I do have a bigger problem with your statement that "If you haven't
modelled the functionality, then you can't expect to use it." It is
the job of the framework to give developers functionality that they
don't have to model. Otherwise Rails would just punt and say "Here's
how you set and read a cookie. If you want to use sessions, model
them yourself."
Posted by Brad Ediger (Guest)
on 2007-03-26 20:49
(Received via mailing list)
I'm not sure you understand the distinction here.

We had server-side sessions before. We still do. They accomplish
everything you are describing, without requiring every developer to
implement an AuthenticatedSession object himself. Look into
ActiveRecordStore in action_controller/session/active_record_store.rb.

This discussion is about the recent move to sessions stored in a
cookie, and how to secure such sessions. I would suggest you go to
Google Groups and read this thread from the beginning to get the
background.
Posted by Neil Wilson (neilw)
on 2007-03-27 17:24
(Received via mailing list)
I understand the distinction very well. I would suggest that you have
ascribed more capability to 'session' than the semantics of that
facility allow.

What I'm saying is that now you have client side session data, you
have exposed the limited semantics of 'session' and there is an issue
that was simply masked by the server side stores.

Rails has never offered authenticated anything. That's why there is no
standard login mechanism.

Why not switch to session side stores and mask the issue, or implement
an AuthenticatedSession that does what you want it to do (and release
it as a plugin if you so desire). Complex cookie encryption might be
an interesting technical puzzle, but is it really required by default?

It's a question again of where the framework ends and the application
begins. I don't believe that there is justification for foisting
complex default encryption mechanisms on the framework when the
'problem' is that you are using the wrong model. Just use a server
side session store.

Now I may be wrong about 'session'. Perhaps it is a much more complex
object than it appears. Perhaps it should be. That is not for me to
decide.

NeilW
Posted by Neil Wilson (neilw)
on 2007-03-27 17:38
(Received via mailing list)
On Mar 26, 7:40 pm, Brad Ediger <b...@bradediger.com> wrote:
> How, exactly, would you model the login session so as to be immune to  
> replay attacks with shared-nothing on the server side?

Use a server side session store, not a client side one.


> I do have a bigger problem with your statement that "If you haven't  
> modelled the functionality, then you can't expect to use it." It is  
> the job of the framework to give developers functionality that they  
> don't have to model. Otherwise Rails would just punt and say "Here's  
> how you set and read a cookie. If you want to use sessions, model  
> them yourself."

Why not go the whole hog and provide us with a default fifteen level
login system with access control lists?

The issue is where the framework ends and the application begins. A
Rails app that just uses the flash and a setting to determine whether
to show the welcome page doesn't need nonces and anti-replay devices.

Perhaps the first job is to step back a little and ask how much you
*really* should stuff into session. What is the job of that little
semi-persistent-hash?

NeilW
Posted by Brad Ediger (Guest)
on 2007-03-27 18:13
(Received via mailing list)
Hi-
Thanks for the levelheaded response. I'm sorry if I was a little
inflammatory before. Occupational hazard. :-)

Comments follow.

On Mar 27, 2007, at 10:24 AM, Neil Wilson wrote:

> I understand the distinction very well. I would suggest that you have
> ascribed more capability to 'session' than the semantics of that
> facility allow.
>
> What I'm saying is that now you have client side session data, you
> have exposed the limited semantics of 'session' and there is an issue
> that was simply masked by the server side stores.

(snip)
> Why not switch to session side stores and mask the issue, or implement
> an AuthenticatedSession that does what you want it to do (and release
> it as a plugin if you so desire). Complex cookie encryption might be
> an interesting technical puzzle, but is it really required by default?

I think we're on the same page here, but maybe coming at it from
opposite directions. I think the session abstraction, as exposed by
the server-side stores, worked fine. I don't think it was masking
anything -- I wouldn't say that every aspect of an application's
semantics needs to be captured explicitly in the model. As an
abstraction, the server-side stores provided everything that
developers needed, even considering sensitive and volatile data
(i.e., authentication information).

The problem comes when you try to change the abstraction. Storing
sensitive data with an untrusted client is always tricky -- it's the
reason that ATM cards are fundamentally more secure than any
anonymous e-cash system. "Complex cookie encryption" covers a lot of
ground... the HMAC will definitely be required if you want any
integrity at all, and some sort of nonce is (provably) required if
replayed sessions can hurt you in any way.

However, I think that it is too much to ask of new developers to
implement the whole AuthenticatedSession thing (along with the
requisite security analysis) themselves. As Robert James pointed out
in this thread, security analysis is really tricky -- there are N
ways to get it wrong and 1 way to get it right. And forcing
developers to consider security at this level isn't too friendly, IMO.

I believe that CookieStore should be either (1) secure against replay
attacks by default, or (2) not the default session store. Anything
else is asking too much of non-security-aware developers.

--be
Posted by Jonathan Weiss (Guest)
on 2007-03-27 21:54
(Received via mailing list)
> I believe that CookieStore should be either (1) secure against replay  
> attacks by default, or (2) not the default session store. Anything  
> else is asking too much of non-security-aware developers.

+ 1

Jonathan


--
Jonathan Weiss
http://blog.innerewut.de
Posted by Isak Hansen (Guest)
on 2007-03-29 10:29
(Received via mailing list)
On 3/21/07, S. Robert James <srobertjames@gmail.com> wrote:
>
> I'm concerned about the possibility of replay attacks with cookie
> sessions.  This is a standard security issue.
>

Just adding my $0.02:

I like the shared-nothing cookie store as an option, for
performance/scalability reasons. Just document the vulnerability to
replay attacks and maybe add a timestamp to limit how long the cookie
remains valid.

The nonce thing adds a lot of complexity, and if you need to hit
shared storage anyway there's just no point. As far as I'm concerned,
updating a nounce or the actual session data has similar overhead.


I'd prefer a db backed session store replacing the current default.
Ideally it would be automatically created, indexed and purged of stale
data.


Isak
Posted by Tomas Jogin (Guest)
on 2007-03-29 11:39
(Received via mailing list)
How about just NOT changing the default setting to this less secure
option? Problem solved.
Posted by Steve Longdo (Guest)
on 2007-03-29 15:29
(Received via mailing list)
Have any metrics been gathered on the "performance/scalability" of the 
new
method or is it imaginary premature optimization?

On 3/29/07, Isak Hansen <isak.hansen@gmail.com> wrote:
> I like the shared-nothing cookie store as an option, for
> Ideally it would be automatically created, indexed and purged of stale
> data.
>
>
> Isak
>
> >
>


--
Thanks,
-Steve
http://www.stevelongdo.com
Posted by Obie Fernandez (Guest)
on 2007-03-29 16:58
(Received via mailing list)
On 3/29/07, Tomas Jogin <tomasj@gmail.com> wrote:
>
> How about just NOT changing the default setting to this less secure
> option? Problem solved.

+ 1  It sounds like the decision to make cookie store the default was
premature, at best.

By the way, just because this 'feature' is in EdgeRails does not mean
it will make it to a *stable* release, which makes some of the
hand-wringing on periphery of this thread seem a little premature
also.
Posted by Jeremy Kemper (Guest)
on 2007-03-29 21:42
(Received via mailing list)
On 3/29/07, Obie Fernandez <obiefernandez@gmail.com> wrote:
> On 3/29/07, Tomas Jogin <tomasj@gmail.com> wrote:
> > How about just NOT changing the default setting to this less secure
> > option? Problem solved.
>
> + 1  It sounds like the decision to make cookie store the default was
> premature, at best.

Planting the seed here led to quick ripening and plenty of pesticide.

> By the way, just because this 'feature' is in EdgeRails does not mean
> it will make it to a *stable* release, which makes some of the
> hand-wringing on periphery of this thread seem a little premature
> also.

Thanks for the fish, all.

jeremy
Posted by Thijs van der Vossen (Guest)
on 2007-03-29 21:44
(Received via mailing list)
On Mar 29, 2007, at 21:35, Jeremy Kemper wrote:
> On 3/29/07, Obie Fernandez <obiefernandez@gmail.com> wrote:
>> On 3/29/07, Tomas Jogin <tomasj@gmail.com> wrote:
>>> How about just NOT changing the default setting to this less secure
>>> option? Problem solved.
>>
>> + 1  It sounds like the decision to make cookie store the default was
>> premature, at best.
>
> Planting the seed here led to quick ripening and plenty of pesticide.

Ok, that _is_ really funny. ;)

Kind regards,
Thijs

--
Fingertips - http://www.fngtps.com
Posted by Brad Ediger (Guest)
on 2007-03-30 00:15
(Received via mailing list)
On Mar 29, 2007, at 2:43 PM, Thijs van der Vossen wrote:

>> Planting the seed here led to quick ripening and plenty of pesticide.
>
> Ok, that _is_ really funny. ;)

I think he's trying for two quotes on project.ioni.st this week. :-)
Posted by John Wilger (jwilger)
on 2007-04-01 19:05
(Received via mailing list)
On Mar 29, 12:35 pm, "Jeremy Kemper" <jer...@bitsweat.net> wrote:
> Planting the seed here led to quick ripening and plenty of pesticide.
<snip>
> Thanks for the fish, all.

So, does that mean this will likely be taken out? If so, I would vote
that it at least be provided as an option if not the default. It's
certainly useful for developers who understand the security concerns
and still feel that it would be an appropriate method of session
storage for their application.

--
Regards,

John Wilger
Posted by Sam Bravard (Guest)
on 2007-09-25 23:00
(Received via mailing list)
Someone on Caboose want to chime in and bring this thread to rest?

Short summary: someone made a well meaning change to sessions that is
broken and creates more pain than it solves.
Desired result: rollback the patch.

DHH, what say you?

On Mar 29, 12:02 am, Thijs van der Vossen <t.vandervos...@gmail.com>
Posted by Pete Yandell (Guest)
on 2007-09-25 23:04
(Received via mailing list)
On 23/03/2007, at 6:19 AM, Brad Ediger wrote:

> (a) Cookie sessions are vulnerable to replay attacks, because the
> client can present *any* cookie that it has seen to the server, not
> just the most recently sent one. On the other hand, server-side
> storage methods are not vulnerable because the session ID always
> references the latest version of the session.

+1 for hitting the nail on the head.
Posted by Thijs van der Vossen (Guest)
on 2007-09-25 23:04
(Received via mailing list)
On Mar 29, 2007, at 3:48, Brad Ediger wrote:
> On Mar 27, 2007, at 9:46 PM, S. Robert James wrote:
>> As I said earlier, I'm waiting for a spec and sample app before
>> working on a full review.
>
> I went ahead and wrote up a spec. Here's my first crack at it.
>
> Everyone: Please feel free to make suggestions / corrections.

I'm probably missing something here, but what exactly is your goal
for this?

Kind regards,
Thijs

--
Fingertips - http://www.fngtps.com
Posted by Robert James (robertjames)
on 2007-09-25 23:04
(Received via mailing list)
There are some other very serious security issues with cookie store as
it stands now.

As I said earlier, I'm waiting for a spec and sample app before
working on a full review.  If those never happen, I'll eventually post
the sketches that I already have.  But I think the community would be
happier with a material "this is how the app can be compromised" over
"theoretically, depending on the implementation, this might be the
problem."  Anyway, if I don't here back on those things, I'll post my
notes from conversation - if I do, I'll try to get a full review done.

On Mar 27, 12:05 pm, "Alexey Verkhovsky" <alexey.verkhov...@gmail.com>
Posted by Brad Ediger (Guest)
on 2007-09-25 23:05
Attachment: smime.p7s (2,36 KB)
(Received via mailing list)
On Mar 27, 2007, at 9:46 PM, S. Robert James wrote:
> As I said earlier, I'm waiting for a spec and sample app before
> working on a full review.

I went ahead and wrote up a spec. Here's my first crack at it.

Everyone: Please feel free to make suggestions / corrections.

--------

-- Rails Sessions

The Rails web application framework provides storage for sessions,
which are small pieces of data that persist across a stream, or
"session," of requests by the same user.

In this document, "user" means a person that makes requests via HTTP
to a server. "Client" refers to a software program (usually a web
browser) acting on the user's behalf.

A session may be used to store any type of data, but it is most
commonly used for the following information:

* A user ID number, which identifies the currently logged-in user
* A "return to" URL, which indicates the location the user should be
sent to after logging in (used when an unauthenticated user tries to
access a restricted page)
* "Flash" information, or short notification and error messages
concerning the status of the user's most recent request

Clearly, the key security requirement is data integrity. The client
is not trusted, and must not be allowed to modify the session, create
sessions, or assume another client's session. All session
modification is performed by the server, which is trusted.

In some cases, the client may not be allowed to read the session
(e.g., account numbers, third-party passwords), but this use of the
session is strongly discouraged. However, it is desired that Rails be
forgiving of session misuse, in that such misuse should not cause
hidden security vulnerabilities where at all possible.

The only action that the client is allowed to directly perform on the
session is abandonment. At any time, the client may make a request
that does not include the session identifier. The server treats this
as a new session. Rails applications are written so that abandonment
of a session at any time does not cause problems.

Rails aims for a "shared-nothing" style of scalability, in which
there may be many application servers running Rails. All shared state
is held in either the database or some custom-engineered repository
(such as memcached). A load balancer is placed in front of the
application servers to distribute requests. This way, any server can
handle any incoming requests. A stream of requests comprising a
session may hit several servers over the course of the session.

-- Server-Side Session Storage

Until February 2007, all storage for sessions took place on the
server. There were several backends that stored sessions on the
filesystem, in a database, or in memory. This provided data integrity
(since these resources can only be modified by the server) and
confidentiality (as the sessions were only trafficked between the
application server or servers). Confidentiality may have been a
detail of implementation rather than a design goal in this instance.

Under server-based storage, the session is indexed by a session ID,
which is an MD5 hash of:

* POSIX time (seconds since epoch)
* Microseconds part of current time
* A pseudorandom number in the interval [0,1), converted to a string
* The application server's process ID
* The string 'foobar'

All of this randomness serves to mitigate session hijacking attacks,
as session IDs cannot be easily guessed. The client is given the
generated session ID in an HTTP cookie. Sessions can expire either
when the browser is closed or after a fixed period of time (between
15 minutes and months to years, depending on the application); this
is controlled by the expiration time on the cookie.

-- Client-Side Session Storage

In February 2006, a new session storage method was introduced and is
now the default for edge (trunk) Rails. The release branches have not
yet switched to this method. This method, the CookieStore, stores the
entire session in Base64 encoding in a cookie.

The CookieStore provides no confidentiality, but integrity is assured
by signing the cookie with an HMAC. SHA-1 is the default. The server
verifies the HMAC every time the cookie is deserialized. The HMAC is
keyed off of a user-supplied secret. For new applications, Rails
creates a secret when the application is generated. The secret is
generated from the session ID algorithm described above, where
'foobar' is replaced with the application's name.

There is a 4 KB limit to the total Base64-encoded data, including the
HMAC. This limit reflects the standard architectural limitation
imposed on HTTP cookies. There is no graceful recovery from an
oversized session -- it is an error to attempt to store more than 4
KB of data in a session under the CookieStore.

The advantages of the CookieStore are twofold: (1) The cookies are
transmitted as part of the standard HTTP request/response cycle, so
there is little session-lookup overhead. The roundtrip to the
database server or shared memory store is eliminated. (2) The server
does not need to keep track of open sessions. This mitigates a
potential denial-of-service vulnerability where a client could open
many sessions and exhaust a server's inodes.

There are some disadvantages, though. All sessions are considered
equal to the server -- it is a consequence of not having to keep
track of every session in progress. Without some shared state (such
as flags on a user account in the database), the server must either
honor all sessions or none of them. There is no way to selectively
delete or expire sessions. Session expiration can be achieved without
shared state if an expiration time is included in the cookie, but
this requires sending a new cookie with each request (cookies are
normally only sent when session data changes).

A more serious problem with the CookieStore is the possibility of
replay attacks. Since the cookie consists only of the session data
signed with an HMAC, a valid session can be saved and replayed later;
it will always be valid at the framework level unless the secret is
changed. The application programmer can introduce time-variant
information to invalidate old sessions (as described above), but from
the framework's perspective, if the server signed it at some point,
it is a valid session.

It has been suggested that a nonce be incorporated into the cookie to
prevent replay attacks. This presents several logistical problems,
though none of them is insurmountable. First, the nonce will
necessarily change with each request and therefore the cookie must be
regenerated, re-signed, and retransmitted to the client with each
request. Secondly, and most importantly, the nonces must be
synchronized among the application servers. This necessitates hitting
the database or another shared store on every request for a nonce
lookup and update.

-----------


--be
Posted by Alexey Verkhovsky (Guest)
on 2007-09-25 23:08
(Received via mailing list)
+1 to:

CookieStore should be either (1) secure against replay
Posted by Brad Ediger (Guest)
on 2007-09-25 23:09
Attachment: smime.p7s (2,36 KB)
(Received via mailing list)
On Mar 29, 2007, at 2:02 AM, Thijs van der Vossen wrote:

> I'm probably missing something here, but what exactly is your goal
> for this?

Koz asked for a security review, Robert James said he might be able
to get one, so I wrote a summary of what has been said / done so far.
I was trying to be neutral but detailed, so that's why it might seem
bland.

--be
Posted by Thijs van der Vossen (Guest)
on 2007-09-25 23:10
(Received via mailing list)
On Mar 29, 2007, at 10:22, Sam Bravard wrote:
> Short summary: someone made a well meaning change to sessions that is
> broken and creates more pain than it solves.
> Desired result: rollback the patch.
>
> DHH, what say you?

The 'someone' was [1] bitsweat aka Jeremy Kemper who works for
37signals where David Heinemeier Hansson is a partner. I suspect
they've talked about this... ;)

Kind regards,
Thijs

[1] http://dev.rubyonrails.org/changeset/6184

--
Fingertips - http://www.fngtps.com
Posted by Brad Ediger (Guest)
on 2007-09-25 23:10
(Received via mailing list)
On Mar 22, 2007, at 2:08 PM, Courtenay wrote:

>> meant.
>
> If you're overly concerned with "user_id" haxoring, just use a guid
> instead of DB id in your User.find

Umm... did you read the thread? No, I'm not forgetting any of that,
and those are not my points at all.

(a) Cookie sessions are vulnerable to replay attacks, because the
client can present *any* cookie that it has seen to the server, not
just the most recently sent one. On the other hand, server-side
storage methods are not vulnerable because the session ID always
references the latest version of the session.

(b) Of course the HMAC would fail if you change the session. I'm not
talking about changing the session. I never was. What worries me is
this:

1. I log in; I get session cookie A which corresponds to
"user_id=12345" with the HMAC and everything.
2. I log out and my session cookie is "deleted" -- in the sense of
not being presented to the server anymore. It may hang out on disk or
memory.
3. Someone finds the session and presents it to the server. Since it
is signed by the server, it is accepted and that user is logged in.

Suddenly, a token which had no value after logout (a session ID) now
has immense value (session cookie) because possession of it allows
one to impersonate me at any time in the future.
This topic is locked and can not be replied to.