public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
Search Repo:
Merge [8176] to stable to fix session fixation attacks.  Closes #10048 
[theflow, Koz]


git-svn-id: 
http://svn-commit.rubyonrails.org/rails/branches/1-2-stable@8177 
5ecf4fe2-1ee6-0310-87b1-e25e094e27de
NZKoz (author)
Tue Nov 20 21:00:25 -0800 2007
commit  63e968794acb4435d44f8706d26f065bdcc79487
tree    0c047c607207805170e110b3489fa9e3b804a5c9
parent  65539c9f4d67ad6da7992645533602540c43740a
...
36
37
38
39
 
40
41
42
43
44
45
 
46
47
48
49
...
50
51
52
53
54
55
56
 
 
 
 
57
58
59
...
114
115
116
117
 
118
119
120
...
36
37
38
 
39
40
41
42
43
44
45
46
47
48
49
50
...
51
52
53
 
54
55
56
57
58
59
60
61
62
63
...
118
119
120
 
121
122
123
124
0
@@ -36,13 +36,14 @@
0
   end
0
 
0
   class CgiRequest < AbstractRequest #:nodoc:
0
- attr_accessor :cgi, :session_options, :cookie_only
0
+ attr_accessor :cgi, :session_options
0
     class SessionFixationAttempt < StandardError; end #:nodoc:
0
 
0
     DEFAULT_SESSION_OPTIONS = {
0
       :database_manager => CGI::Session::PStore,
0
       :prefix => "ruby_sess.",
0
       :session_path => "/",
0
+ :session_key => "_session_id",
0
       :cookie_only => true
0
     } unless const_defined?(:DEFAULT_SESSION_OPTIONS)
0
 
0
0
@@ -50,10 +51,13 @@
0
       @cgi = cgi
0
       @session_options = session_options
0
       @env = @cgi.send(:env_table)
0
- @cookie_only = session_options.delete :cookie_only
0
       super()
0
     end
0
 
0
+ def cookie_only?
0
+ session_options_with_string_keys['cookie_only']
0
+ end
0
+
0
     def query_string
0
       if (qs = @cgi.query_string) && !qs.empty?
0
         qs
0
@@ -114,7 +118,7 @@
0
           @session = Hash.new
0
         else
0
           stale_session_check! do
0
- if @cookie_only && request_parameters[session_options_with_string_keys['session_key']]
0
+ if cookie_only? && request_parameters[session_options_with_string_keys['session_key']]
0
               raise SessionFixationAttempt
0
             end
0
             case value = session_options_with_string_keys['new_session']
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
0
@@ -1 +1,93 @@
0
+require File.dirname(__FILE__) + '/../abstract_unit'
0
+
0
+class SessionFixationTest < Test::Unit::TestCase
0
+ class MockCGI < CGI #:nodoc:
0
+ attr_accessor :stdoutput, :env_table
0
+
0
+ def initialize(env, data = '')
0
+ self.env_table = env
0
+ self.stdoutput = StringIO.new
0
+ super(StringIO.new(data))
0
+ end
0
+ end
0
+
0
+ class TestController < ActionController::Base
0
+ session :session_key => '_myapp_session_id', :secret => 'secret', :except => :default_session_key
0
+ session :cookie_only => false, :only => :allow_session_fixation
0
+
0
+ def default_session_key
0
+ render :text => "default_session_key"
0
+ end
0
+
0
+ def custom_session_key
0
+ render :text => "custom_session_key: #{params[:id]}"
0
+ end
0
+
0
+ def allow_session_fixation
0
+ render :text => "allow_session_fixation"
0
+ end
0
+
0
+ def rescue_action(e) raise end
0
+ end
0
+
0
+ def setup
0
+ @controller = TestController.new
0
+ end
0
+
0
+ def test_should_be_able_to_make_a_successful_request
0
+ cgi = mock_cgi_for_request_to(:custom_session_key, :id => 1)
0
+
0
+ assert_nothing_raised do
0
+ @controller.send(:process, mock_request(cgi), ActionController::CgiResponse.new(cgi))
0
+ end
0
+ assert_equal 'custom_session_key: 1', @controller.response.body
0
+ assert_not_nil @controller.session
0
+ end
0
+
0
+ def test_should_catch_session_fixation_attempt
0
+ cgi = mock_cgi_for_request_to(:custom_session_key, :_myapp_session_id => 42)
0
+
0
+ assert_raises ActionController::CgiRequest::SessionFixationAttempt do
0
+ @controller.send(:process, mock_request(cgi), ActionController::CgiResponse.new(cgi))
0
+ end
0
+ assert_nil @controller.session
0
+ end
0
+
0
+ def test_should_not_catch_session_fixation_attempt_when_cookie_only_setting_is_disabled
0
+ cgi = mock_cgi_for_request_to(:allow_session_fixation, :_myapp_session_id => 42)
0
+
0
+ assert_nothing_raised do
0
+ @controller.send(:process, mock_request(cgi), ActionController::CgiResponse.new(cgi))
0
+ end
0
+ assert !@controller.response.body.blank?
0
+ assert_not_nil @controller.session
0
+ end
0
+
0
+ def test_should_catch_session_fixation_attempt_with_default_session_key
0
+ ActionController::Base.session_store = :p_store # using the default session_key is not possible with cookie store
0
+ cgi = mock_cgi_for_request_to(:default_session_key, :_session_id => 42)
0
+
0
+ assert_raises ActionController::CgiRequest::SessionFixationAttempt do
0
+ @controller.send(:process, mock_request(cgi) , ActionController::CgiResponse.new(cgi))
0
+ end
0
+ assert @controller.response.body.blank?
0
+ assert_nil @controller.session
0
+ end
0
+
0
+private
0
+
0
+ def mock_cgi_for_request_to(action, params = {})
0
+ MockCGI.new({
0
+ "REQUEST_METHOD" => "GET",
0
+ "QUERY_STRING" => "action=#{action}&#{params.to_query}",
0
+ "REQUEST_URI" => "/",
0
+ "SERVER_PORT" => "80",
0
+ "HTTP_HOST" => "testdomain.com" }, '')
0
+ end
0
+
0
+ def mock_request(cgi)
0
+ ActionController::CgiRequest.new(cgi, {})
0
+ end
0
+
0
+end

Comments

    No one has commented yet.