NYCPHP Meetup

NYPHP.org

[nycphp-talk] Experts help needed (Sessions)

Joseph Crawford codebowl at gmail.com
Mon Aug 1 19:22:16 EDT 2005


Guys,

I have the following code in use however people can easilly hijack sessions 
i am not sure why but when a session is hijacked the IP address in the 
database changes, yet the session values are retained. Here is the code.



<?php

class session
{
/* Define the mysql table you wish to use with
this class, this table MUST exist. */
private $table = "sessions";
private $_db;
private $_page;
private $_sess_id;
private $_ip;
private $_browser;
private $_browserList;
private $_os;
private $_osList;
static private $_type;
private $_typeIcon;


public function __construct(Database $db) {
$this->_db = $db;

$this->_browserList = array('offbyone' => 'ob1.gif', '3b_web' => '3b.gif', 
'getrig' => 'get.gif', 'webtv' => 'webtv.gif', 'aol' => 'aol.gif', 'opera' 
=> 'opera.gif', 'netposit' => 'netp.gif', 'ibrowse' => 'ibrowse.gif', 
'abrowse' => 'abrowse.gif', 'firefox' => 'firefox.gif', 'firebird' => '
firebird.gif', 'phoenix' => 'firebird.gif', 'omniweb' => 'omni.gif', 
'safari' => 'safari.gif', 'camino' => 'camino.gif', 'chimera' => 'camino.gif', 
'konqueror' => 'konq.gif', 'icab' => 'icab.gif', 'dillo' => 'dillo.gif', 
'epiphany' => 'epiph.gif', 'oregano' => 'oregano.gif', 'k-meleon' => '
kmel.gif', 'webcapture' => 'webcap.gif', 'galeon' => 'galeon.gif', 'lynx' => 
'lynx.gif', 'netscape' => 'netscape.gif', 'entergy' => 'entergy.gif', 'msie' 
=> 'ie.gif', 'mozilla' => 'moz.gif');
$this->_osList = array('linspire' => 'linspire.gif', 'lindows' => '
linspire.gif', 'beos' => 'beos.gif', 'skyos' => 'skyos.gif', 'atheos' => '
athe.gif', 'palmos' => 'palm.gif', 'nokia' => 'nokia.gif', 'blackberry' => '
blackb.gif', 'zeta' => 'zeta.gif', 'irix' => 'irix.gif', 'risc' => '
riscos.gif', 'os/2' => 'os2.gif', 'amigaos' => 'amiga.gif', 'freebsd' => '
fbsd.gif', 'netbsd' => 'nbsd.gif', 'sunos' => 'solaris.gif', 'solaris' => '
solaris.gif', 'os x' => 'osx.gif', 'osx' => 'osx.gif', 'darwin' => 'osx.gif', 
'macintosh' => 'macintosh.gif', 'mac_' => 'macintosh.gif', 'qnx' => 'qnx.gif', 
'linux' => 'linux.gif', 'unix' => 'unix.gif', 'x11' => 'x11.gif', 'windows' 
=> 'windows.gif', 'win95' => 'windows.gif', 'win98' => 'windows.gif', 
'winnt' => 'windows.gif');
self::setType();
}

private function init() {
if(!isset($this->_sess_id)) $this->_sess_id = session_id();
$this->_page = $_SERVER['REQUEST_URI'];
if(!isset($this->_ip)) $this->_ip = $_SERVER['REMOTE_ADDR'];
if(!isset($this->_typeIcon)) $this->setUserIcon();
if(!isset($this->_browser)) $this->setUserBrowser();
if(!isset($this->_os)) $this->setUserOS();

$this->CheckIP();
}

public function open($path, $name) {

return TRUE;
}

/* Close session */
public function close() {
/* This is used for a manual call of the
session gc function */
$this->gc(0);
return TRUE;
}

/* Read session data from database */
public function read($ses_id) {

$session_sql = "SELECT * FROM " . $this->table
. " WHERE ses_id = '$ses_id'";

$session_res = $this->_db->Query($session_sql);
if (!$session_res) {
return '';
}

$session_num = $this->_db->NumRows($session_res);
if ($session_num > 0) {
$session_row = $this->_db->FetchArray($session_res);
$ses_data = $session_row["ses_value"];
return $ses_data;
} else {
return '';
}
}

/* Write new data to database */
public function write($ses_id, $data) {
$this->init();
$session_sql = "
INSERT INTO "
.$this->table." (ses_id, type, typeicon, ses_time, ses_start, page, ip, 
browser, os, ses_value)
VALUES 
('".$ses_id."', '".self::$_type."', '".$this->_typeIcon."', ".time().", 
".time().", '".$this->_page."', '".$this->_ip."', '".$this->_browser."', 
'".$this->_os."', '".$data."') 
ON DUPLICATE KEY UPDATE 
type='".self::$_type."', typeicon='".$this->_typeIcon."', 
ses_time=".time().", page='".$this->_page."', ses_value='".$data."'";
$session_res = $this->_db->Query($session_sql);
if (!$session_res) return FALSE;
else return TRUE;

}

/* Destroy session record in database */
public function destroy($ses_id) {
$session_sql = "DELETE FROM " . $this->table
. " WHERE ses_id = '$ses_id'";

$session_res = $this->_db->Query($session_sql);
if (!$session_res) return FALSE;
else return TRUE;
}

/* Garbage collection, deletes old sessions */
public function gc($life) {
$ses_life = strtotime("-5 minutes");

$session_sql = "DELETE FROM " . $this->table
. " WHERE ses_time < $ses_life";

$session_res = $this->_db->Query($session_sql);


if (!$session_res) return FALSE;
else return TRUE;
}

private function CheckIP() {
echo '<br>'.$this->_ip.'<br>';
echo $_SERVER['REMOTE_ADDR'];
if( strcmp($this->_ip, $_SERVER['REMOTE_ADDR']) ) {
echo 'YOU HAVE HIJACKED A SESSION, SESSION DESTROYED!';
$sess_sql = "DELETE FROM ".$this->table." WHERE 
ses_id='".$this->_sess_id."'";
$this->_db->Query($sess_sql);
session_destroy();
}
}

private function setUserIcon() {
switch(self::$_type) {
case 'AD':
$this->_typeIcon .= 'images/icons/user/admin.png';
break;
case 'CL':
$this->_typeIcon .= 'images/icons/user/client.png';
break;
case 'CO':
$this->_typeIcon .= 'images/icons/user/contractor.png';
break;
default:
$this->_typeIcon .= 'images/icons/user/guest.png';
}
}

private function setUserBrowser() {
foreach ($this->_browserList as $browser => $img) {
if(stristr($_SERVER['HTTP_USER_AGENT'], $browser)) {
$this->_browser .= 'images/icons/browser/'.$img;
break;
}
}
}

private function setUserOS() {
foreach ($this->_osList as $os => $img) {
if(stristr($_SERVER['HTTP_USER_AGENT'], $os)) {
$this->_os .= 'images/icons/os/'.$img;
break;
}
}
}

static public function setType( $type = 'GU' ) {
$type = substr($type, 0, 2);
if(isset($type) && is_string($type) && strlen($type) == 2) self::$_type = 
strtoupper($type);
}
}
?>

you can see that you can hijack a session by going to this page

http://codebowl.homelinux.net:8001/csaf/test.php?PHPSESSID=0615292083a9ea7010f1fe935597751e

you can also use a browser to open the page and create a session, then open 
a different browser like IE or Firefox (but not the same browser) and hijack 
your own session, as i have the page printing the session id so you can get 
it.

I am not sure why when a session is hijacked the IP in the database is 
updated, this should not be the case. The SQL query i have in my write 
method should not do anything but insert or update if it exists.

Any help i would really appreciate. I like the flexibility of sessions in 
the database but i dont like the idea of how easy it is to hijack the 
session without the system noticing and destroying it.

-- 
Joseph Crawford Jr.
Codebowl Solutions, Inc.
1-802-671-2021
codebowl at gmail.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.nyphp.org/pipermail/talk/attachments/20050801/ae85724d/attachment.html>


More information about the talk mailing list