On Feb 12, 8:05 am, Michael Koziarski <[email protected]> wrote:
> CSRF attacks are about using *session* data to perform an action
> without the user's knowledge.  The attack you're describing here,
> which doesn't rely on session data, could also be performed just using
> curl from the command line of the attackers laptop, there's no need to
> involve the user's computer at all.

Except for him not being able to vote twice using curl with the same
IP address.
The attack allows him to command other people (his visitors) to
perform actions on my site.
In my opionion, the 'session riding' part of CSRF is not just about
the physical session/cookie object, just as much about starting new
sessions. (so session as in "the order in which requests are made", we
only allow a signup if you first asked for the signup form).
But no matter what we think CSRF protection is about, the old behavior
was about validating every potentially harmful request, the new one a
specific type of attack, which was already covered by the old one.
So we can conclude that the security got loosened somewhat (for
reasons you mention below).

>
> If there's no involvement of the session (or some other
> client-browser-specific) vector, then it's not a CSRF attack.

As mentioned, I think starting a new sessions from a "clean" IP
address counts as client-browser specific.

>
> However you're correct that we need a little more documentation than
> we had previously because the attack vectors are a touch trickier.  I
> intend to post an FAQ blog post and update the guides in a few days to
> ensure that it's crystal clear what's required.

I'm glad we agree documentation is the key.

>
> The thing to remember is that we *can't* raise an exception in the
> default case any more because *every api request would be rejected*.
> For users who don't have any API, then the original behaviour was
> probably fine.  However a large portion of rails apps do and we can't
> completely break them!

That's why my API controllers inherit from ApiController instead of
ApplicationController, and I don't put the CSRF protection in there.
Instead, api calls need an API key param to verify their origin. Also
there's "skip_before_filter :verify_authenticity_token" to bypass CSRF
protection on a controller or action basis.
This is probably what most apps with an API use, because - as you
point out - there are already a large number of rails apps out there
with an API, working with the old system. So I don't see how they
would be broken.

I agree it's nice we can now configure the behavior ourselves, instead
of having to fully bypass it, all I'm saying is that for the default
case making sure a request is dropped sounds best to me. The API case
should indeed be able to easily switch to other behavior (for certain
controllers probably).


> I see your point and agree that we need a little more documentation
> around this.  However it is nowhere near as simple as your suggestions
> imply.  Developers will have to understand the implications of their
> choices.

Indeed, of their own choices.
But since the default (rails generator) "application" already contains
'protect_from_forgery', which just doesn't do anything unless they
start using the session as a security measure, you can't really hold
every dev responsible for expecting that they are protected against
forged requests from other sites.

>
> I suspect we'll end up with an api like:
>
> protect_from_forgery :on_failure=>:raise
> protect_from_forgery :on_failure=>:reset
> protect_from_forgery :on_failure=>:some_method
> protect_from_forgery :on_failure=> proc { ... }

That sounds like a nice api

>
> I realise that the previous situation where you could just ignore the
> issue was greatly preferable, but that was based on some assumptions
> which don't hold.  The old rules don't apply anymore.

I don't really see why. The old system was easy to bypass for specific
controllers and actions, while the default was safe for all abuse-
cases. The new system is aimed towards applications with an api that
don't want to use skip_before_filter and that do use a session for
their security-measures.
What assumption does not hold anymore? Which rule changed?



>
>
>
>
>
>
>
>
>
> > Mathijs
>
> > On Feb 11, 9:51 pm, Jon Leighton <[email protected]> wrote:
> >> Hi there,
>
> >> As you've identified, the difference between 2.3.10 and 2.3.11, and
> >> between 3.0.3 and 3.0.4, in how they handle invalid csrf tokens is that
> >> the former will raise ActionController::InvalidAuthenticityToken, but
> >> the latter will reset the session.
>
> >> What we are trying to protect against is the following situation:
>
> >> * Alice is logged in to Facebook
> >> * Alice visits badsite.com
> >> * Mallory, who owns badsite.com has added some code into the page which
> >> makes a request to facebook.com and posts on Alice's wall.
> >> * Alice visits badsite.com and without her intending it to be, a comment
> >> is posted on her wall
>
> >> With the current CSRF protection, the following will happen:
>
> >> * Alice is logged in to Facebook
> >> * Alice visits badsite.com
> >> * Mallory, who owns badsite.com has added some code into the page which
> >> makes a request to facebook.com and posts on Alice's wall.
> >> * Alice visits badsite.com and without her intending it to be, a request
> >> is made to post on her wall
> >> * Facebook detects that there is no CSRF token associated with the
> >> request, and so logs her out by resetting the session
> >> * Then, based on the authorisation rules within the application,
> >> Facebook denies to post on the wall, because the user is not logged in
>
> >> With the old CSRF protection, the following will happen:
>
> >> * Alice is logged in to Facebook
> >> * Alice visits badsite.com
> >> * Mallory, who owns badsite.com has added some code into the page which
> >> makes a request to facebook.com and posts on Alice's wall.
> >> * Alice visits badsite.com and without her intending it to be, a request
> >> is made to post on her wall
> >> * Facebook detects that there is no CSRF token associated with the
> >> request and so refuses to serve the request in any way (returns 500)
> >> * So nothing gets posted on the wall
>
> >> The point is, they are different but both have the effect of preventing
> >> the wall post.
>
> >> If for some reason you specifically want an exception to be raised in
> >> this situation, you can customise handle_unverified_request, but it
> >> doesn't compromise the aim of the CSRF protection to no raise an
> >> exception, so long as the request is not allowed to go through as
> >> authenticated by the existing session.
>
> >> Jon
>
> >> On Fri, 2011-02-11 at 11:28 -0800, Mathijs wrote:
> >> > Hi all,
>
> >> > I think CSFR protection broke in rails 2.3.11.
> >> > As in: it's turned off now.
>
> >> > I tried this in rails 2.3.10 and in 2.3.11 and 2.3.11 seems broken.
>
> >> > >rails csrftest
> >> > >cd csrftest
> >> > >script/generate scaffold post title:string
> >> > >rake db:migrate
>
> >> > now I visit /posts/new in my browser, use firebug to delete or change
> >> > the authenticity token, and submit the form.
>
> >> > rails 2.3.11: all fine, new post saved
> >> > rails 2.3.10: ActionController::InvalidAuthenticityToken
>
> >> > I checked ApplicationController to see if it still contained
> >> > "protect_from_forgery", which is the case.
> >> > I read the announcement for the csrf changes in 2.3.11 and they talk
> >> > about overriding handle_unverified_request for special cases where
> >> > there are other ways for authenticating a user. In this simple case I
> >> > demonstrated though, there is no concept of a user or logging in (or a
> >> > session), so the default action of resetting the session is not very
> >> > useful.
> >> > In my opinion, CSRF protection is about verifying a request. It
> >> > doesn't have anything to do with users/sessions/authentication.
> >> > By default, a faulty request (unprotected/wrong token) should not
> >> > reach the normal controller action code at all, so the main action to
> >> > take when a non-verified request comes in, is to have the
> >> > before_filter chain halt. nothing more, nothing less.
> >> > Extra stuff (like destroying a session) is up to the user (or nice to
> >> > leave in as a default).
> >> > So I think the behavior in 2.3.11 is just wrong, because in the
> >> > example I gave, the forms just get submitted and stuff gets persisted
> >> > to the database.
> >> > It's not clear from the announcement at all that you should now make
> >> > sure the filter chain halts, or that you must protect your actions by
> >> > something that's stored in the session (because that's all that gets
> >> > done when a faulty request hits).
>
> >> > Maybe I'm just doing something wrong here, please let me know.
> >> > Mathijs
>
> >> --http://jonathanleighton.com/
>
> >>  signature.asc
> >> < 1KViewDownload
>
> > --
> > You received this message because you are subscribed to the Google Groups 
> > "Ruby on Rails: Core" group.
> > To post to this group, send email to [email protected].
> > To unsubscribe from this group, send email to 
> > [email protected].
> > For more options, visit this group 
> > athttp://groups.google.com/group/rubyonrails-core?hl=en.
>
> --
> Cheers
>
> Koz

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Core" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-core?hl=en.

Reply via email to