1
0
Fork 0
mirror of https://github.com/sinatra/sinatra synced 2023-03-27 23:18:01 -04:00

implement session hijacking prevention

This commit is contained in:
Konstantin Haase 2011-05-29 13:01:47 +02:00
parent 3588ba5d33
commit 012cd7be0f
4 changed files with 54 additions and 12 deletions

View file

@ -16,10 +16,10 @@ module Rack
class AuthenticityToken < Base
def accepts?(env)
return true if safe? env
request = Request.new env
session = session env
token = session[:csrf] ||= session['_csrf_token'] || random_string
env['HTTP_X_CSRF_TOKEN'] == token or
request.params['authenticity_token'] == token
Request.new(env).params['authenticity_token'] == token
end
end
end

View file

@ -1,4 +1,5 @@
require 'rack/protection'
require 'digest'
require 'logger'
require 'uri'
@ -6,8 +7,9 @@ module Rack
module Protection
class Base
DEFAULT_OPTIONS = {
:reaction => :default_reaction, :logging => true, :status => 403,
:message => 'Forbidden'
:reaction => :default_reaction, :logging => true,
:message => 'Forbidden', :encryptor => Digest::SHA1,
:session_key => 'rack.session', :status => 403
}
attr_reader :app, :options
@ -55,8 +57,17 @@ module Rack
[options[:status], {'Content-Type' => 'text/plain'}, [options[:message]]]
end
def session?(env)
env.include? options[:session_key]
end
def session(env)
env['rack.session'] ||= {}
return env[options[:session_key]] if session? env
fail "you need to set up a session middleware *before* #{self.class}"
end
def drop_session(env)
session(env).clear if session? env
end
def referrer(env)
@ -70,13 +81,13 @@ module Rack
random_string false
end
def drop_session(env)
env['rack.session'] = {}
end
def default_reaction(env)
fail "no default reaction given for #{self.class}"
end
def encrypt(value)
options[:encryptor].hexdigest value.to_s
end
end
end
end

View file

@ -14,6 +14,24 @@ module Rack
#
# Not Yet Implemented!
class SessionHijacking < Base
default_options :tracking_key => :tracking, :encrypt_tracking => true,
:track => %w[HTTP_USER_AGENT HTTP_ACCEPT_ENCODING HTTP_ACCEPT_LANGUAGE
HTTP_VERSION]
def accepts?(env)
session = session env
key = options[:tracking_key]
if session.include? key
session[key].all? { |k,v| env[k] == encrypt(v) }
else
session[key] = {}
options[:track].each { |k| session[k] = encrypt(env[k]) }
end
end
def encrypt(value)
options[:encrypt_tracking] ? super(value) : value.to_s
end
end
end
end

View file

@ -20,9 +20,18 @@ module TestHelpers
end
def mock_app(app = nil, &block)
app = block if app.nil? and block.arity == 1
app = app ? Rack::Head.new(described_class.new(app)) : Rack::Builder.new(&block).to_app
@app = Rack::Lint.new(app)
app = block if app.nil? and block.arity == 1
if app
klass = described_class
mock_app do
use Rack::Head
use Rack::Session::Cookie
use klass
run app
end
else
@app = Rack::Lint.new Rack::Builder.new(&block).to_app
end
end
def with_headers(headers)
@ -89,6 +98,8 @@ shared_examples_for 'any rack application' do
end
mock_app do
use Rack::Head
use Rack::Session::Cookie
use detector
use klass
run DummyApp
@ -114,6 +125,8 @@ shared_examples_for 'any rack application' do
end
mock_app do
use Rack::Head
use Rack::Session::Cookie
use detector
use klass
use changer