class Rack::Protection::CookieTossing
- session_key
- The name of the session cookie (default: ‘rack.session’)
Options:
session cookie. This does not protect against a cookie overflow attack.
Does not accept HTTP requests if the HTTP_COOKIE header contains more than one
More infos - github.com/blog/1466-yummy-cookies-across-domains<br>Supported browsers
- all
Prevented attack -
Cookie Tossing
#
- all
- The name of the session cookie (default: ‘rack.session’)
def accepts?(env)
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) || (k != session_key && Rack::Utils.unescape(k) == session_key) bad_cookies << k end end bad_cookies.empty? end
def bad_cookies
def bad_cookies @bad_cookies ||= [] end
def call(env)
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
def cookie_paths(path)
def cookie_paths(path) path = '/' if path.to_s.empty? paths = [] Pathname.new(path).descend { |p| paths << p.to_s } paths end
def empty_cookie(host, path)
def empty_cookie(host, path) { value: '', domain: host, path: path, expires: Time.at(0) } end
def redirect(env)
def redirect(env) request = Request.new(env) warn env, "attack prevented by #{self.class}" [302, { 'content-type' => 'text/html', 'location' => request.path }, []] end
def remove_bad_cookies(request, response)
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
def session_key
def session_key @session_key ||= options[:session_key] end