From 21ac1c9210204ff05189fbc8a00337f4108477e6 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Sat, 28 Dec 2013 14:07:44 -0500 Subject: [PATCH] Add CSRF protection to every API call --- endpoints/common.py | 22 ++++++++++++++++++++++ static/js/app.js | 6 +++++- templates/base.html | 1 + 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/endpoints/common.py b/endpoints/common.py index d6bd0125a..25e25abf3 100644 --- a/endpoints/common.py +++ b/endpoints/common.py @@ -1,5 +1,8 @@ import logging +import os +import base64 +from flask import request, make_response, jsonify, abort, url_for, session from flask.ext.login import login_user, UserMixin from flask.ext.principal import identity_changed @@ -46,3 +49,22 @@ def common_login(db_user): else: logger.debug('User could not be logged in, inactive?.') return False + + +@app.before_request +def csrf_protect(): + if request.method != "GET" and request.method != "HEAD": + token = session.get('_csrf_token', None) + found_token = request.args.get('_csrf_token', request.form.get('_csrf_token', None)) + + # TODO: add if not token here, once we are sure all sessions have a token. + if token != found_token: + abort(403) + + +def generate_csrf_token(): + if '_csrf_token' not in session: + session['_csrf_token'] = base64.b64encode(os.urandom(48)) + return session['_csrf_token'] + +app.jinja_env.globals['csrf_token'] = generate_csrf_token diff --git a/static/js/app.js b/static/js/app.js index 414c05357..ee5136b99 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -724,7 +724,7 @@ quayApp = angular.module('quay', ['ngRoute', 'chieffancypants.loadingBar', 'rest otherwise({redirectTo: '/'}); }]). config(function(RestangularProvider) { - RestangularProvider.setBaseUrl('/api/'); + RestangularProvider.setBaseUrl('/api/'); }); @@ -2204,6 +2204,10 @@ quayApp.directive('ngBlur', function() { quayApp.run(['$location', '$rootScope', 'Restangular', 'UserService', 'PlanService', '$http', '$timeout', function($location, $rootScope, Restangular, UserService, PlanService, $http, $timeout) { + + // Handle session security. + Restangular.setDefaultRequestParams({'_csrf_token': window.__token || ''}); + // Handle session expiration. Restangular.setErrorInterceptor(function(response) { if (response.status == 401) { diff --git a/templates/base.html b/templates/base.html index af71c9bde..2fdbca35a 100644 --- a/templates/base.html +++ b/templates/base.html @@ -67,6 +67,7 @@