Here's my entire custom sessions implementation:

https://gist.github.com/862824

I'm using my own MongoDB abstraction layer for persistence:
https://gist.github.com/862824

Sessions are persisted in the database, and only the session id is stored in
the cookie, so sessions can be arbitrarily large without much penalty, which
is pretty convenient. :)  MongoDB is pretty sweet for stuff like this, since
frequently accessed objects are in RAM and access is extremely fast, so I'm
not worried about the extra penalty of reading the session with every
request.

<https://gist.github.com/862824>Steve


On Wed, Mar 9, 2011 at 11:24 AM, Stephen Lacy <slacy+perso...@slacy.com>wrote:

> CSRF protection is a fairly complex topic, and Pyramid's brief textual
> description in the docs above really glosses over many of the important
> aspects of how to handle CSRF protection.
>
> In my form handling view, I'm using code that looks like this:
>
>     if not request.session.csrf_valid(request.POST['csrft']):
>         return HTTPInternalServerError()
>
> and, of course, I have a custom session factory and an implementation of
> csrf_valid on my session that looks like this:
>
>         @wrap_access
>         def csrf_valid(self, csrf_token):
>             """Check to see if the CSRF value is valid, and rotate the CSRF
>             value at the end of the request."""
>             equal = (csrf_token == self.get_csrf_token())
>             if not equal:
>                 logging.warning("CSRF INVALID: %s != %s",
>                                 csrf_token, self.get_csrf_token())
>             # Once the CSRF is checked, we say that we should rotate the
>             # CSRF token at the end of this request.  We only rotate the
>             # CSRF token if it's actually checked, otherwise we just keep
>             # plugging along with the same one.
>             self.rotate_csrf_token()
>             return equal
>
> (@wrap_access is the same as what's going on in the base session, and
> rotate_csrf_token just sets a flag that's checked in my response_callback
> method.  That code gets a new CSRF token and stores it in the session)
>
> The key question you need to think about when implementing CSRF checking is
> "when should I generate a new CSRF token?".  You can't generate a new CSRF
> token with every request, because of things like AJAX and loading of other
> resources (images, CSS, js) that are coming through your server.  Remember
> that your server is going to be hit several times for each "page."
>
> What I decided on was "generate a new token every time I check the current
> token".  This isn't perfect, but it works in most cases where the user is
> using my site in a single browser window.  If users open multiple windows
> (with multiple forms) then CSRF validation will fail, which still sort of
> sucks. (possible solution below)
>
> If you have more complex needs (like CSRF protection for forms that are
> asynchronously generated, multiple forms in parallel, etc.) then you'll need
> a much more sophisticated system than what's provided above.  For example,
> you might want to keep track of the last dozen or so CSRF tokens, and
> consider all of those "good" for the checking in csrf_valid done above.   Of
> course, this gets troublesome when your session is stored in a cookie, as
> large sessions are bad style and can make your site slower.  So, I'm storing
> sessions in a database (MongoDB) on the server.
>
> I've been meaning to read over Django's @csrf_protect decorator and see
> what kind of behavior it implements, because it would be a good starting
> point for most of these requirements.
> http://docs.djangoproject.com/en/dev/ref/contrib/csrf/ and
> https://github.com/django/django/blob/master/django/views/decorators/csrf.pyand
> https://github.com/django/django/blob/master/django/middleware/csrf.py  It
> looks like they're only checking CSRF for POST requests, and they explicitly
> say "make sure your GET requests don't have any side effects".  This seems a
> bit naive, because you could still have a DDoS-type CSRF attack via GETs
> (i.e. hammering a search form, etc.).
>
> On a cursory inspection, it looks like they validate the CSRF token from
> the session with every request.  This is a reasonable approach, and would
> seem to eliminate the unnecessary csrf_token field in the form, but totally
> breaks multiple browser windows for a single session, which seems like a bad
> tradeoff.
>
> Steve
>
> On Wed, Mar 9, 2011 at 8:20 AM, Chris Withers <ch...@simplistix.co.uk>wrote:
>
>> On 09/03/2011 15:10, danjac...@gmail.com wrote:
>>
>>> I've got a simplistic example here:
>>>
>>> http://packages.python.org/pyramid_simpleform/#csrf-validation
>>>
>>
>> I'm afraid this doesn't actually answer either of my questions:
>>
>>
>>  First, the important question: If I use
>>>>
>>>> http://docs.pylonsproject.org/projects/pyramid/1.0/narr/sessions.html#using-the-default-session-factory
>>>> is the CSRF protection provided by
>>>>
>>>> http://docs.pylonsproject.org/projects/pyramid/1.0/narr/sessions.html#preventing-cross-site-request-forgery-attacks
>>>> still secure and effective?
>>>>
>>>> The less important question: which tracker should I use for
>>>> documentation
>>>> feature requests?
>>>>
>>>
>> cheers,
>>
>> Chris
>>
>> --
>> Simplistix - Content Management, Batch Processing & Python Consulting
>>           - http://www.simplistix.co.uk
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "pylons-devel" group.
>> To post to this group, send email to pylons-devel@googlegroups.com.
>> To unsubscribe from this group, send email to
>> pylons-devel+unsubscr...@googlegroups.com.
>> For more options, visit this group at
>> http://groups.google.com/group/pylons-devel?hl=en.
>>
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"pylons-devel" group.
To post to this group, send email to pylons-devel@googlegroups.com.
To unsubscribe from this group, send email to 
pylons-devel+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/pylons-devel?hl=en.

Reply via email to