mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
SECURITY: correct our CSRF implementation to be much more aggressive
This commit is contained in:
@@ -132,8 +132,11 @@ Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||
|
||||
// Add a CSRF token to all AJAX requests
|
||||
var csrfToken = $('meta[name=csrf-token]').attr('content');
|
||||
|
||||
$.ajaxPrefilter(function(options, originalOptions, xhr) {
|
||||
if (!options.crossDomain) {
|
||||
// This may be delay set
|
||||
csrfToken = csrfToken || $('meta[name=csrf-token]').attr('content');
|
||||
xhr.setRequestHeader('X-CSRF-Token', csrfToken);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -46,7 +46,7 @@ Discourse.Ajax = Em.Mixin.create({
|
||||
return Ember.RSVP.resolve(fixture);
|
||||
}
|
||||
|
||||
return Ember.Deferred.promise(function (promise) {
|
||||
var performAjax = function(promise) {
|
||||
var oldSuccess = args.success;
|
||||
args.success = function(xhr) {
|
||||
Ember.run(promise, promise.resolve, xhr);
|
||||
@@ -69,7 +69,22 @@ Discourse.Ajax = Em.Mixin.create({
|
||||
if ((!args.dataType) && (args.type === 'GET')) args.dataType = 'json';
|
||||
|
||||
$.ajax(Discourse.getURL(url), args);
|
||||
});
|
||||
};
|
||||
|
||||
// For cached pages we strip out CSRF tokens, need to round trip to server prior to sending the
|
||||
// request (bypass for GET, not needed)
|
||||
var csrfToken = $('meta[name=csrf-token]').attr('content');
|
||||
if(args.type && args.type !== 'GET' && !csrfToken){
|
||||
return Ember.Deferred.promise(function(promise){
|
||||
$.ajax(Discourse.getURL('/session/csrf'))
|
||||
.success(function(result){
|
||||
$('head').append('<meta name="csrf-token" content="' + result.csrf + '">');
|
||||
performAjax(promise);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return Ember.Deferred.promise(performAjax);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -14,6 +14,18 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
protect_from_forgery
|
||||
|
||||
# Default Rails 3.2 lets the request through with a blank session
|
||||
# we are being more pedantic here and nulling session / current_user
|
||||
# and then raising a CSRF exception
|
||||
def handle_unverified_request
|
||||
# NOTE: API key is secret, having it invalidates the need for a CSRF token
|
||||
unless is_api?
|
||||
super
|
||||
clear_current_user
|
||||
raise Discourse::CSRF
|
||||
end
|
||||
end
|
||||
|
||||
before_filter :inject_preview_style
|
||||
before_filter :block_if_maintenance_mode
|
||||
before_filter :authorize_mini_profiler
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
class SessionController < ApplicationController
|
||||
# we need to allow account login with bad CSRF tokens, if people are caching, the CSRF token on the
|
||||
# page is going to be empty, this means that server will see an invalid CSRF and blow the session
|
||||
# once that happens you can't log in with social
|
||||
skip_before_filter :verify_authenticity_token, only: [:create]
|
||||
|
||||
skip_before_filter :redirect_to_login_if_required
|
||||
|
||||
def csrf
|
||||
render json: {csrf: form_authenticity_token }
|
||||
end
|
||||
|
||||
def create
|
||||
params.require(:login)
|
||||
params.require(:password)
|
||||
|
||||
@@ -15,7 +15,8 @@ class Users::OmniauthCallbacksController < ApplicationController
|
||||
# need to be able to call this
|
||||
skip_before_filter :check_xhr
|
||||
|
||||
# must be done, cause we may trigger a POST
|
||||
# this is the only spot where we allow CSRF, our openid / oauth redirect
|
||||
# will not have a CSRF token, however the payload is all validated so its safe
|
||||
skip_before_filter :verify_authenticity_token, only: :complete
|
||||
|
||||
def complete
|
||||
|
||||
Reference in New Issue
Block a user