From 9cc05ca9160a9432d037afb9cc22c511e2542947 Mon Sep 17 00:00:00 2001 From: Scott Torborg Date: Sun, 8 Nov 2009 15:54:09 -0800 Subject: [PATCH] added XSRF protection to all forms and associated tests --- bluechips/controllers/spend.py | 3 ++- bluechips/controllers/transfer.py | 2 ++ bluechips/controllers/user.py | 2 ++ bluechips/lib/helpers.py | 1 + bluechips/templates/spend/index.mako | 1 + bluechips/templates/transfer/index.mako | 1 + bluechips/templates/user/index.mako | 1 + bluechips/tests/functional/test_spend.py | 22 +++++++++++++----- bluechips/tests/functional/test_transfer.py | 25 ++++++++++++++++----- bluechips/tests/functional/test_user.py | 6 ++++- 10 files changed, 51 insertions(+), 13 deletions(-) diff --git a/bluechips/controllers/spend.py b/bluechips/controllers/spend.py index aceb6ad..098ac27 100644 --- a/bluechips/controllers/spend.py +++ b/bluechips/controllers/spend.py @@ -9,8 +9,8 @@ from decimal import Decimal, InvalidOperation from bluechips.lib.base import * from pylons import request, app_globals as g -from pylons.decorators.rest import dispatch_on from pylons.decorators import validate +from pylons.decorators.secure import authenticate_form from pylons.controllers.util import abort from formencode import validators, Schema @@ -91,6 +91,7 @@ class SpendController(BaseController): return render('/spend/index.mako') @redirect_on_get('edit') + @authenticate_form @validate(schema=ExpenditureSchema(), form='edit', variable_decode=True) def update(self, id=None): # Either create a new object, or, if we're editing, get the diff --git a/bluechips/controllers/transfer.py b/bluechips/controllers/transfer.py index 5094845..ed06018 100644 --- a/bluechips/controllers/transfer.py +++ b/bluechips/controllers/transfer.py @@ -10,6 +10,7 @@ from bluechips.lib.base import * from pylons import request, app_globals as g from pylons.decorators import validate +from pylons.decorators.secure import authenticate_form from pylons.controllers.util import abort from formencode import Schema, validators @@ -48,6 +49,7 @@ class TransferController(BaseController): return render('/transfer/index.mako') @redirect_on_get('edit') + @authenticate_form @validate(schema=TransferSchema(), form='edit') def update(self, id=None): if id is None: diff --git a/bluechips/controllers/user.py b/bluechips/controllers/user.py index df8253e..b432126 100644 --- a/bluechips/controllers/user.py +++ b/bluechips/controllers/user.py @@ -11,6 +11,7 @@ from sqlalchemy import orm from pylons import request from pylons.decorators import validate +from pylons.decorators.secure import authenticate_form from formencode import validators, Schema @@ -28,6 +29,7 @@ class UserController(BaseController): c.title = 'User Settings' return render('/user/index.mako') + @authenticate_form @validate(schema=EmailSchema(), form='index') def update(self): new_email = self.form_result['new_email'] diff --git a/bluechips/lib/helpers.py b/bluechips/lib/helpers.py index 1a05266..8da5a57 100644 --- a/bluechips/lib/helpers.py +++ b/bluechips/lib/helpers.py @@ -6,6 +6,7 @@ available to Controllers. This module is available to both as 'h'. from routes import url_for, redirect_to from webhelpers.html import escape, literal, url_escape from webhelpers.html.tags import * +from webhelpers.html.secure_form import * from webhelpers.pylonslib import Flash as _Flash diff --git a/bluechips/templates/spend/index.mako b/bluechips/templates/spend/index.mako index 25f1db2..ff388a3 100644 --- a/bluechips/templates/spend/index.mako +++ b/bluechips/templates/spend/index.mako @@ -5,6 +5,7 @@ %>
+ ${h.auth_token_hidden_field()} diff --git a/bluechips/templates/transfer/index.mako b/bluechips/templates/transfer/index.mako index 736c339..7c3daa9 100644 --- a/bluechips/templates/transfer/index.mako +++ b/bluechips/templates/transfer/index.mako @@ -1,6 +1,7 @@ <%inherit file="/base.mako"/> + ${h.auth_token_hidden_field()}
diff --git a/bluechips/templates/user/index.mako b/bluechips/templates/user/index.mako index c293252..af8d3a6 100644 --- a/bluechips/templates/user/index.mako +++ b/bluechips/templates/user/index.mako @@ -4,6 +4,7 @@

Enter an email address below if you wish to be notified of any updates to transactions involving you. Leave blank to not receive notifications.

+ ${h.auth_token_hidden_field()}
diff --git a/bluechips/tests/functional/test_spend.py b/bluechips/tests/functional/test_spend.py index 801c580..125ac06 100644 --- a/bluechips/tests/functional/test_spend.py +++ b/bluechips/tests/functional/test_spend.py @@ -1,6 +1,8 @@ from datetime import date from formencode import Invalid +from webhelpers.html.secure_form import token_key + from bluechips.tests import * from bluechips import model @@ -111,11 +113,21 @@ class TestSpendController(TestController): id=124234), status=404) def test_update_nonexistent(self): - response = self.app.post(url_for(controller='spend', - action='update', - id=14234), - params=self.sample_post, - status=404) + response = self.app.get(url_for(controller='spend', + action='edit')) + params = self.sample_post.copy() + params[token_key] = response.form[token_key].value + self.app.post(url_for(controller='spend', + action='update', + id=14234), + params=params, + status=404) + + def test_xsrf_protection(self): + self.app.post(url_for(controller='spend', + action='update'), + params=self.sample_post, + status=403) def test_all_zero_shares_fails(self): params = self.sample_post.copy() diff --git a/bluechips/tests/functional/test_transfer.py b/bluechips/tests/functional/test_transfer.py index 9e01e6a..69eba46 100644 --- a/bluechips/tests/functional/test_transfer.py +++ b/bluechips/tests/functional/test_transfer.py @@ -1,7 +1,9 @@ from datetime import date from decimal import Decimal -from bluechips.tests import * +from webhelpers.html.secure_form import token_key + +from bluechips.tests import * from bluechips import model from bluechips.model import meta @@ -76,11 +78,22 @@ class TestTransferController(TestController): id=21424), status=404) def test_update_nonexistent(self): - response = self.app.post(url_for(controller='transfer', - action='update', - id=21424), - params=self.sample_params, - status=404) + response = self.app.get(url_for(controller='transfer', + action='edit')) + params = self.sample_params.copy() + params[token_key] = response.form[token_key].value + self.app.post(url_for(controller='transfer', + action='update', + id=21424), + params=params, + status=404) + + def test_xsrf_protection(self): + self.app.post(url_for(controller='transfer', + action='update'), + params=self.sample_params, + status=403) + def test_update_get_redirects(self): response = self.app.get(url_for(controller='transfer', diff --git a/bluechips/tests/functional/test_user.py b/bluechips/tests/functional/test_user.py index b5c9136..c27983b 100644 --- a/bluechips/tests/functional/test_user.py +++ b/bluechips/tests/functional/test_user.py @@ -30,4 +30,8 @@ class TestUserController(TestController): filter_by(username=unicode(config['fake_username'])).one() assert user.email == None - + def test_xsrf_protection(self): + self.app.post(url_for(controller='user', + action='update'), + {'new_email': 'malicious@example.com'}, + status=403) -- 2.45.2