Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #10048: fix_broken_session_fixation_catching.patch

File fix_broken_session_fixation_catching.patch, 4.9 kB (added by theflow, 1 year ago)
  • actionpack/test/controller/session_fixation_test.rb

    old new  
     1require File.dirname(__FILE__) + '/../abstract_unit' 
     2 
     3class SessionFixationTest < Test::Unit::TestCase 
     4  class MockCGI < CGI #:nodoc: 
     5    attr_accessor :stdoutput, :env_table 
     6 
     7    def initialize(env, data = '') 
     8      self.env_table = env 
     9      self.stdoutput = StringIO.new 
     10      super(nil, StringIO.new(data)) 
     11    end 
     12  end 
     13 
     14  class TestController < ActionController::Base 
     15    session :session_key => '_myapp_session_id', :secret => 'secret', :except => :default_session_key 
     16    session :cookie_only => false, :only => :allow_session_fixation 
     17 
     18    def default_session_key 
     19      render :text => "default_session_key" 
     20    end 
     21 
     22    def custom_session_key 
     23      render :text => "custom_session_key: #{params[:id]}" 
     24    end 
     25 
     26    def allow_session_fixation 
     27      render :text => "allow_session_fixation" 
     28    end 
     29 
     30    def rescue_action(e) raise end 
     31  end 
     32 
     33  def setup 
     34    @controller = TestController.new 
     35  end 
     36 
     37  def test_should_be_able_to_make_a_successful_request 
     38    cgi = mock_cgi_for_request_to(:custom_session_key, :id => 1) 
     39 
     40    assert_nothing_raised do 
     41      @controller.send(:process, ActionController::CgiRequest.new(cgi, {}), ActionController::CgiResponse.new(cgi)) 
     42    end 
     43    assert_equal 'custom_session_key: 1', @controller.response.body 
     44    assert_not_nil @controller.session 
     45  end 
     46 
     47  def test_should_catch_session_fixation_attempt 
     48    cgi = mock_cgi_for_request_to(:custom_session_key, :_myapp_session_id => 42) 
     49 
     50    assert_raises ActionController::CgiRequest::SessionFixationAttempt do 
     51      @controller.send(:process, ActionController::CgiRequest.new(cgi, {}), ActionController::CgiResponse.new(cgi)) 
     52    end 
     53    assert_nil @controller.session 
     54  end 
     55 
     56  def test_should_not_catch_session_fixation_attempt_when_cookie_only_setting_is_disabled 
     57    cgi = mock_cgi_for_request_to(:allow_session_fixation, :_myapp_session_id => 42) 
     58 
     59    assert_nothing_raised do 
     60      @controller.send(:process, ActionController::CgiRequest.new(cgi, {}), ActionController::CgiResponse.new(cgi)) 
     61    end 
     62    assert ! @controller.response.body.blank? 
     63    assert_not_nil @controller.session 
     64  end 
     65 
     66  def test_should_catch_session_fixation_attempt_with_default_session_key 
     67    ActionController::Base.session_store = :p_store # using the default session_key is not possible with cookie store 
     68    cgi = mock_cgi_for_request_to(:default_session_key, :_session_id => 42) 
     69 
     70    assert_raises ActionController::CgiRequest::SessionFixationAttempt do 
     71      @controller.send(:process, ActionController::CgiRequest.new(cgi, {}), ActionController::CgiResponse.new(cgi)) 
     72    end 
     73    assert @controller.response.body.blank? 
     74    assert_nil @controller.session 
     75  end 
     76 
     77private 
     78 
     79  def mock_cgi_for_request_to(action, params = {}) 
     80    MockCGI.new({ 
     81      "REQUEST_METHOD" => "GET", 
     82      "QUERY_STRING"   => "action=#{action}&#{params.to_query}", 
     83      "REQUEST_URI"    => "/", 
     84      "SERVER_PORT"    => "80", 
     85      "HTTP_HOST"      => "testdomain.com" }, '') 
     86  end 
     87 
     88end 
  • actionpack/lib/action_controller/cgi_process.rb

    old new  
    3333  end 
    3434 
    3535  class CgiRequest < AbstractRequest #:nodoc: 
    36     attr_accessor :cgi, :session_options, :cookie_only 
     36    attr_accessor :cgi, :session_options 
    3737    class SessionFixationAttempt < StandardError; end #:nodoc: 
    3838 
    3939    DEFAULT_SESSION_OPTIONS = { 
    4040      :database_manager => CGI::Session::CookieStore, # store data in cookie 
    4141      :prefix           => "ruby_sess.",    # prefix session file names 
    4242      :session_path     => "/",             # available to all paths in app 
     43      :session_key      => "_session_id", 
    4344      :cookie_only      => true 
    4445    } unless const_defined?(:DEFAULT_SESSION_OPTIONS) 
    4546 
     
    4748      @cgi = cgi 
    4849      @session_options = session_options 
    4950      @env = @cgi.send!(:env_table) 
    50       @cookie_only = session_options.delete :cookie_only 
    5151      super() 
    5252    end 
    5353 
     
    112112          @session = Hash.new 
    113113        else 
    114114          stale_session_check! do 
    115             if @cookie_only && request_parameters[session_options_with_string_keys['session_key']] 
     115            if cookie_only? && query_parameters[session_options_with_string_keys['session_key']] 
    116116              raise SessionFixationAttempt 
    117117            end 
    118118            case value = session_options_with_string_keys['new_session'] 
     
    158158        end 
    159159      end 
    160160 
     161      def cookie_only? 
     162        session_options_with_string_keys['cookie_only'] 
     163      end 
     164 
    161165      def stale_session_check! 
    162166        yield 
    163167      rescue ArgumentError => argument_error