Implementing Session Support COEN 351 State Maintenance Client Side Mechanisms Cookies Hidden Fields in Forms Each page has to be rebuild to contain correct form Fat URL Client needs to allow cookies Cookie handling done by browser Each page has to be rebuild with correct links Server Side Mechanisms Files Database Web server Long running process that can crash Needs to use a client side mechanism Security Implication: CLIENT CAN CHANGE ALL INFORMATION Server Side Support Apache:Session Perl module failed test for windows CGI:Session Homemade Session Support Use to investigate security issues Using a session database mysql> mysql> mysql> -> -> -> -> create database session; use session; create table sessionid ( id MEDIUMINT NOT NULL AUTO_INCREMENT, name CHAR(30) NOT NULL, PRIMARY KEY (id) ); Using a session database mysql> show tables; +-------------------+ | Tables_in_session | +-------------------+ | sessionid | +-------------------+ 1 row in set (0.00 sec) mysql> INSERT INTO sessionid (name) VALUES ('thomas'); Query OK, 1 row affected (0.10 sec) mysql> INSERT INTO sessionid (name) VALUES ('bob'),('jim'); Query OK, 2 rows affected (0.04 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM sessionid ORDER BY id; +----+--------+ | id | name | +----+--------+ | 1 | thomas | | 2 | bob | | 3 | jim | +----+--------+ 3 rows in set (0.00 sec) Creating a Password Database mysql> create table user ( -> name VARCHAR(8), -> password VARCHAR(8), -> primary key (name) -> ); Query OK, 0 rows affected (0.16 sec) mysql> INSERT INTO user -> VALUES ('JoeDoe','12345'), ('JaneDoe','12345') -> ; Query OK, 2 rows affected (0.09 sec) Records: 2 Duplicates: 0 Warnings: 0 Sample Application Login Page Typically form that is self-referring When user info is submitted, page acts differently Acceptance page that creates a session Stores session id in cookie Login Page #!/perl/bin/perl.exe use strict; use CGI qw/:standard/; use MIME::Base64::URLSafe; #I had problems with this module under build 819 More normal: -action => url() my $q = new CGI; print print print print $q->header(-type => "text/html"); $q->start_html("Santa Claus University Login Page"); $q->h1("Welcome to Santa Claus University"); $q->start_form( -action => "session1.cgi", -method => 'GET'), $q->p("Please enter your account"), $q->textfield (-name => "name"), $q->p("Please enter your password"), $q->textfield (-name => "pwd"), $q->p(" "), $q->submit (-name => 'choice', -value => "Submit" ), $q->end_form(); print $q->end_html; Login Page <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US"> <head> <title>Santa Claus University Login Page</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> </head> <body> <h1>Welcome to Santa Claus University</h1><form method="get" action="session1.cgi" enctype="multipart/form-data"> <p>Please enter your account</p><input type="text" name="name" value="thomas" /><p>Please enter your password</p><input type="text" name="pwd" value="hallo" /><p> </p><input type="submit" name="choice" value="Submit" /></form> </body> </html> Notice that there is currently no protection for the data to be transmitted. Creating a Session Use MySQL database with autoincrement feature: mysql> describe sessionid; +-------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+----------------+ | id | mediumint(9) | NO | PRI | NULL | auto_increment | | name | char(30) | NO | | | | +-------+--------------+------+-----+---------+----------------+ 2 rows in set (0.15 sec) Creating a Session #!/perl/bin/perl.exe use strict; use DBI; use CGI qw/:standard :html3/; use CGI::Carp qw/ fatalsToBrowser/; #for debugging only use MIME::Base64::URLSafe; #I had problems with this module under build 819 my $q = new CGI; #Get information from GET data: my $username = param('name'); my $pwd = param('pwd'); Creating a Session my $dbh = DBI->connect ("DBI:mysql:host=localhost;database=session", "root", "none",{PrintError => 0, RaiseError => 1} ); my $sth = $dbh->prepare("SELECT * FROM user WHERE name = '$username' and password = '$pwd' "); $sth->execute(); my $ref = $sth->fetchrow_hashref (); $sth->finish(); if (!defined($ref)) { print "Location: http://192.168.0.13/cgibin/session.cgi\n\n" } Possibility of SQL injection attack! else { code on next page } Would it be better to check results? Creating a Session else { #create entry in sessionid, get session ID, and clean up table $dbh->do ("INSERT INTO sessionID (id,name) VALUES(NULL,'$username')" ); my $ref = $dbh->selectcol_arrayref("SELECT LAST_INSERT_ID()"); my $sessionid = @{$ref}[0]; $dbh->do("DELETE LOW_PRIORITY FROM sessionid WHERE id < '$sessionid' and name = '$username'"); mysql> select * from sessionid; +----+---------+ | id | name | +----+---------+ | 41 | JoeDoe | | 42 | JaneDoe | +----+---------+ 2 rows in set (0.05 sec) Clean up session table Is this code vulnerable to a race condition? Creating a Session else } { … my $cookievalue1 = urlsafe_b64encode($sessionid); my $cookievalue2 = urlsafe_b64encode($username); my $cookie1 = $q->cookie ( -name => 'sessionID', -value => $cookievalue1, -expires => "+1d" ); my $cookie2 = $q->cookie ( -name => 'account', -value => $cookievalue2, -expires => "+1d" ); print $q->header(-type => "text/html", -cookie => [$cookie1,$cookie2]); print $q->start_html("Santa Claus University Login Page"); print $q->h1("Welcome to Santa Claus University"); print $q->start_form( -action => "session2.cgi", -method => 'GET'), $q->hidden($cookievalue1), $q->submit (-name => 'Continue', -value => "Submit" ), $q->end_form(); print $q->end_html; Cookie values are not protected! Maintaining Session Data use strict; use DBI; use CGI qw/:standard :html3/; use CGI::Carp qw/ fatalsToBrowser/; use MIME::Base64::URLSafe; my $q = new CGI; print $q->header(-type => "text/html"); print $q->start_html("Santa Claus University Login Page"), $q->h1("Welcome to Santa Claus University"), $q->p("We offer degrees for money."); foreach my $name ($q->cookie()) { my $value = urlsafe_b64decode($q->cookie($name)); print $q->p("$value"); } print $q->end_html; No authentication of cookie values. Security Problems We need to use cookies / fat URLs to refer to the current session name. This information needs to be protected against alteration against substitution