Class: Rack::Protection::CookieTossing

Inherits:
Base
  • Object
show all
Defined in:
lib/rack/protection/cookie_tossing.rb

Overview

Prevented attack

Cookie Tossing

Supported browsers

all

More infos

github.com/blog/1466-yummy-cookies-across-domains

Does not accept HTTP requests if the HTTP_COOKIE header contains more than one session cookie. This does not protect against a cookie overflow attack.

Options:

session_key

The name of the session cookie (default: ‘rack.session’)

Constant Summary

Constants inherited from Base

Base::DEFAULT_OPTIONS

Instance Attribute Summary

Attributes inherited from Base

#app, #options

Instance Method Summary collapse

Methods inherited from Base

default_options, #default_options, default_reaction, #deny, #drop_session, #encrypt, #html?, #initialize, #instrument, #origin, #random_string, #react, #referrer, #report, #safe?, #secure_compare, #session, #session?, #warn

Constructor Details

This class inherits a constructor from Rack::Protection::Base

Instance Method Details

#accepts?(env) ⇒ Boolean

Returns:

  • (Boolean)


28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/rack/protection/cookie_tossing.rb', line 28

def accepts?(env)
  cookie_header = env['HTTP_COOKIE']
  cookies = Rack::Utils.parse_query(cookie_header, ';,') { |s| s }
  cookies.each do |k, v|
    if k == session_key && Array(v).size > 1
      bad_cookies << k
    elsif k != session_key && Rack::Utils.unescape(k) == session_key
      bad_cookies << k
    end
  end
  bad_cookies.empty?
end

#bad_cookiesObject



55
56
57
# File 'lib/rack/protection/cookie_tossing.rb', line 55

def bad_cookies
  @bad_cookies ||= []
end

#call(env) ⇒ Object



20
21
22
23
24
25
26
# File 'lib/rack/protection/cookie_tossing.rb', line 20

def call(env)
  status, headers, body = super
  response = Rack::Response.new(body, status, headers)
  request = Rack::Request.new(env)
  remove_bad_cookies(request, response)
  response.finish
end


59
60
61
62
63
64
# File 'lib/rack/protection/cookie_tossing.rb', line 59

def cookie_paths(path)
  path = '/' if path.to_s.empty?
  paths = []
  Pathname.new(path).descend { |p| paths << p.to_s }
  paths
end


66
67
68
# File 'lib/rack/protection/cookie_tossing.rb', line 66

def empty_cookie(host, path)
  {:value => '', :domain => host, :path => path, :expires => Time.at(0)}
end

#redirect(env) ⇒ Object



49
50
51
52
53
# File 'lib/rack/protection/cookie_tossing.rb', line 49

def redirect(env)
  request = Request.new(env)
  warn env, "attack prevented by #{self.class}"
  [302, {'Content-Type' => 'text/html', 'Location' => request.path}, []]
end

#remove_bad_cookies(request, response) ⇒ Object



41
42
43
44
45
46
47
# File 'lib/rack/protection/cookie_tossing.rb', line 41

def remove_bad_cookies(request, response)
  return if bad_cookies.empty?
  paths = cookie_paths(request.path)
  bad_cookies.each do |name|
    paths.each { |path| response.set_cookie name, empty_cookie(request.host, path) }
  end
end

#session_keyObject



70
71
72
# File 'lib/rack/protection/cookie_tossing.rb', line 70

def session_key
  @session_key ||= options[:session_key]
end