C::P::Session - branche session_fixation: new method change_session_id (incl. doc...
KMX [Tue, 7 Jul 2009 21:54:46 +0000 (21:54 +0000)]
lib/Catalyst/Plugin/Session.pm
t/lib/SessionTestApp.pm
t/live_session_fixation.t

index 8e3a2da..f69b179 100644 (file)
@@ -288,6 +288,24 @@ sub _clear_session_instance_data {
     $c->maybe::next::method(@_); # allow other plugins to hook in on this
 }
 
+sub change_session_id {
+    my $c = shift;
+
+    my $sessiondata = $c->session;
+    my $oldsid = $c->sessionid;
+    my $newsid = $c->create_session_id;
+               
+    if ($oldsid) {
+        $c->log->debug(qq/change_sessid: deleting session data from "$oldsid"/) if $c->debug;
+        $c->delete_session_data("${_}:${oldsid}") for qw/session expires flash/;
+    }
+
+    $c->log->debug(qq/change_sessid: storing session data to "$newsid"/) if $c->debug;
+    $c->store_session_data( "session:$newsid" => $sessiondata );
+
+    return $newsid; 
+}
+
 sub delete_session {
     my ( $c, $msg ) = @_;
 
@@ -749,6 +767,31 @@ an hour.
 
 Note that these values are not auto extended.
 
+=item change_session_id
+
+By calling this method you can force a session id change while keeping all
+session data. This method might come handy when you are paranoid about some
+advanced variations of session fixation attack.
+
+If you want to prevent this session fixation scenario:
+
+    0) let us have WebApp with anonymous and authenticated parts
+    1) a hacker goes to vulnerable WebApp and gets a real sessionid, 
+       just by browsing anonymous part of WebApp
+    2) the hacker inserts (somehow) this values into a cookie in victim's browser
+    3) after the victim logs into WebApp the hacker can enter his/her session
+
+you should call change_session_id in your login controller like this:
+
+      if ($c->authenticate( { username => $user, password => $pass } )) {
+        # login OK
+        $c->change_session_id;
+        ...
+      } else {
+        # login FAILED
+        ...
+      }
+
 =back
 
 =head1 INTERNAL METHODS
index 406b672..504cd30 100644 (file)
@@ -53,8 +53,7 @@ sub dump_session : Global {
 
 sub change_sessid : Global {
     my ( $self, $c ) = @_;
-    #$c->change_session_id;
-    $c->create_session_id;
+    $c->change_session_id;
     $c->res->output("session id changed");
 }
 
index fef7873..3eeb3e9 100644 (file)
@@ -18,7 +18,7 @@ BEGIN {
     or plan skip_all =>
         'Test::WWW::Mechanize::Catalyst >= 0.51 is required for this test';
 
-    plan tests => 8;
+    plan tests => 10;
 }
 
 use lib "t/lib";