Whoops, that second link was broken.  Here's the right link:
http://github.com/slacy/minimongo

Steve

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

> 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