File rubygem-actionpack-1.12.x_session_fixation_attack_v2.patch of Package rubygem-actionpack-1_12
Index: lib/action_controller/cgi_process.rb
===================================================================
--- lib/action_controller/cgi_process.rb (revision 8190)
+++ lib/action_controller/cgi_process.rb (working copy)
@@ -11,8 +11,8 @@
# (default). Additionally, there is CGI::Session::DRbStore and CGI::Session::ActiveRecordStore. Read more about these in
# lib/action_controller/session.
# * <tt>:session_key</tt> - the parameter name used for the session id. Defaults to '_session_id'.
- # * <tt>:session_id</tt> - the session id to use. If not provided, then it is retrieved from the +session_key+ parameter
- # of the request, or automatically generated for a new session.
+ # * <tt>:session_id</tt> - the session id to use. If not provided, then it is retrieved from the +session_key+ cookie, or
+ # automatically generated for a new session.
# * <tt>:new_session</tt> - if true, force creation of a new session. If not set, a new session is only created if none currently
# exists. If false, a new session is never created, and if none currently exists and the +session_id+ option is not set,
# an ArgumentError is raised.
@@ -22,7 +22,9 @@
# server.
# * <tt>:session_secure</tt> - if +true+, this session will only work over HTTPS.
# * <tt>:session_path</tt> - the path for which this session applies. Defaults to the directory of the CGI script.
- def self.process_cgi(cgi = CGI.new, session_options = {})
+ # * <tt>:cookie_only</tt> - if +true+ (the default), session IDs will only be accepted from cookies and not from
+ # the query string or POST parameters. This protects against session fixation attacks.
+ def self.process_cgi(cgi = CGI.new, session_options = {})
new.process_cgi(cgi, session_options)
end
@@ -33,11 +35,14 @@
class CgiRequest < AbstractRequest #:nodoc:
attr_accessor :cgi, :session_options
+ class SessionFixationAttempt < StandardError; end #:nodoc:
DEFAULT_SESSION_OPTIONS = {
:database_manager => CGI::Session::PStore,
:prefix => "ruby_sess.",
- :session_path => "/"
+ :session_path => "/",
+ :session_key => "_session_id",
+ :cookie_only => true
} unless const_defined?(:DEFAULT_SESSION_OPTIONS)
def initialize(cgi, session_options = {})
@@ -47,6 +52,10 @@
super()
end
+ def cookie_only?
+ session_options_with_string_keys['cookie_only']
+ end
+
def query_string
if (qs = @cgi.query_string) && !qs.empty?
qs
@@ -106,6 +115,9 @@
@session = Hash.new
else
stale_session_check! do
+ if cookie_only? && request_parameters[session_options_with_string_keys['session_key']]
+ raise SessionFixationAttempt
+ end
if session_options_with_string_keys['new_session'] == true
@session = new_session
else