add JSON CSRF protection

This commit is contained in:
Konstantin Haase 2011-06-19 15:26:39 +02:00
parent ec0df5969b
commit 62dd794011
5 changed files with 40 additions and 3 deletions

View File

@ -40,6 +40,7 @@ Prevented by:
* `Rack::Protection::AuthenticityToken` (not included by `use Rack::Protection`)
* `Rack::Protection::FormToken` (not included by `use Rack::Protection`)
* `Rack::Protection::JsonCsrf`
* `Rack::Protection::NoReferrer` (not included by `use Rack::Protection`)
* `Rack::Protection::RemoteReferrer` (not included by `use Rack::Protection`)
* `Rack::Protection::RemoteToken`

View File

@ -8,6 +8,7 @@ module Rack
autoload :EscapedParams, 'rack/protection/escaped_params'
autoload :FormToken, 'rack/protection/form_token'
autoload :FrameOptions, 'rack/protection/frame_options'
autoload :JsonCsrf, 'rack/protection/json_csrf'
autoload :NoReferrer, 'rack/protection/no_referrer'
autoload :PathTraversal, 'rack/protection/path_traversal'
autoload :RemoteReferrer, 'rack/protection/remote_referrer'
@ -21,6 +22,7 @@ module Rack
Rack::Builder.new do
use EscapedParams, options unless except.include? :escaped_params
use FrameOptions, options unless except.include? :frame_options
use JsonCsrf, options unless except.include? :json_csrf
use PathTraversal, options unless except.include? :path_traversal
use RemoteToken, options unless except.include? :remote_token
use SessionHijacking, options unless except.include? :session_hijacking

View File

@ -41,10 +41,14 @@ module Rack
def call(env)
unless accepts? env
warn env, "attack prevented by #{self.class}"
result = send(options[:reaction], env)
return result if Array === result and result.size == 3
result = react env
end
app.call(env)
result or app.call(env)
end
def react(env)
result = send(options[:reaction], env)
result if Array === result and result.size == 3
end
def warn(env, message)

View File

@ -0,0 +1,25 @@
require 'rack/protection'
module Rack
module Protection
##
# Prevented attack:: CSRF
# Supported browsers:: all
# More infos:: http://flask.pocoo.org/docs/security/#json-security
#
# JSON GET APIs are volnurable to being embedded as JavaScript while the
# Array prototype has been patched to track data. Checks the referrer
# even on GET requests if the content type is JSON.
class JsonCsrf < AuthenticityToken
default_reaction :deny
def call(env)
status, headers, body = app.call(env)
if headers['Content-Type'].to_s.split(';', 2).first.strip == 'application/json'
result = react(env) if referrer(env) != Request.new(env).host
end
result or [status, headers, body]
end
end
end
end

View File

@ -0,0 +1,5 @@
require File.expand_path('../spec_helper.rb', __FILE__)
describe Rack::Protection::JsonCsrf do
it_behaves_like "any rack application"
end