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:
parent
3588ba5d33
commit
012cd7be0f
4 changed files with 54 additions and 12 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -21,8 +21,17 @@ module TestHelpers
|
|||
|
||||
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)
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue