Regenerate session ID without invalidating the previous one? - php

I have a situation where my system detects if cookie has been hijacked. If I clone the cookie between two different browsers, then my system can kill the session cookie on a browser that is the clone and thus protect the original session.
But I have a problem. How can I regenerate a new session ID value for the cloned browser in the same session? I would essentially give clone a new session ID that is clean of the original session ID data, without affecting the original session ID data.
This is what currently happens on my clone:
System detects that this session was started with a different fingerprint, thus it is a clone or hijacked cookie
Session data is made inaccessible, previous session data is written to disk with session_write_close() and after that the $_SESSION variable is cleared entirely.
User agent (browser) is notified to remove that cloned session cookie
What I want to happen though is that the cookie would not be deleted, but assigned with a new - different - session ID, so that instead of deleting the current session, a new one would be made that is empty.
I cannot use session_regenerate_id(), because that wants sessions to be started and it would start the previous session rather than a new one and my previous original session data would be lost and not accessible from the previous one. I can assign a new session ID with a session_id() function and then use that, but how can I generate the session ID value that is as secure as the one that PHP itself generates?
Basically all I want to do is that if I detect a cloned session, then I still want to start sessions, but I want to replace the session ID of the cloned session while keeping the original session still alive.

Alright, apparently it is doable with session_regenerate_id() method that accepts a variable that basically says whether it should keep previous session data or not. Using this I was able to code a workaround.

Related

Managing multiple users in php

I am a newbie to php.
I just learned that you can create a session variable for a user after his login such as
$_SESSION['id']=****some value(say 3)******;
and this session variable is maintained as long as he doesn't log out(i.e. you clear this session variable using session_destroy).
Now , I have a confusion that if another user logs in then won't this id variable be overwritten thus logging the previous user out?
If this is true ,then what can I do to resolve it?
PHP sessions are tied to a user by a unique (random) ID string, generated the first time you invoke session_start() for a user. That ID is stored in the client browser as a cookie (or possibly via hidden form fields/query parameters).
Even though $_SESSION is used throughout the code, the CONTENTS of that $_SESSION array are tied to a particular user via that ID string. That means if I hit your site, $_SESSION will contain my details. If you hit your site, $_SESSION will contain your details.
There should be no practical way for my details to "leak" in your session, or vice versa. Destroying my session will not destroy yours, because yours is a completely different session, with a different ID.
All sessions are tied to a unique session ID. This is typically set inside the user's cookie.

How do I troubleshoot Issues with sessions?

Related
Sessions - Sessions and Statefullness
Sessions - Sessions are Stateful, PHP user code is not
Sessions - Where to use session_start()
Sessions - Statefullness and Runs
Sessions - vs. Mysql
PHP.net
session_start()
session_id()
session_destroy()
Specefic Two ID issue
Sessions - extra ID created
Sessions - extra ID created - Cookie Location
How can I determine what is the mechanism which causes session_start to create new sessions wrather than resume a previous one?
This is visible in the PHP sourcecode for the session_start function. You need to read the C-code and compare with your usage.
From what I know about sessions, session_start won't start a new session if already one is active. To find out if a session is already active, please see How to tell if a session is active?.
However if a session is started (and it didn't existed earlier) and then closed and you create a new session in the same request, PHP might think that the session does not exists (because the cookie from the browser is still empty). So then a second, also new, session will be started.
If you're unsure what does what, just create yourself a test script where you play around with scenarios.
A possible scenario:
Browser sends request
PHP starts
session_start() is called. No session cookie exists, PHP will create a new session id and will create cookie headers.
you close the session.
session_start() is called. No session cookie exists (in the request), PHP will create a new session id and will create cookie headers.
Two sessions have been created of which one will not be used by the browser for subsequent requests (the session id header for the cookie has been "overwritten" (the last cookie header replaces previous ones for the cookie in question).
To debug things, headers_list can be useful as well as $_COOKIES.
Let me explain how a session work, PHP saves the variables somewhere on the server side (doesn't matter where for the sake of this explanation), and assosiates it with a unique id (i.e. the Session ID), it then gives the session ID to the user in one of two ways:
Via a GET variable in the url (example.com/index.php?sid=acd6e41ac5ae1dc6ae15dec56)
Via a Cookie sent in the headers.
In the next request, PHP will expect to recieve that ID (in one of the two ways mentioned above), and match that against the list of session IDs it has on the server side. Once a match is found, PHP will load the session environment (accessed by the author using the $_SESSION super global).
You describe a problem where PHP does not find a match, and generates a new session ID instead of continuing with an existing one. This means, probably, that there is a problem in the way the client sends the session ID to the server.
That would mean one of two problems:
User has accessed the site without the GET variable that includes the session id: (example.com instead of example.com/index.php?sid=acd6e41ac5ae1dc6ae15dec56).
User has no enabled cookies or has deleted his cookies in between his session.
Check for these two, it is not likely to be a problem in the PHP engine.
Under php.net session_id()
In php version 5.3.2 in my case each time a new session-id was
generated after session_start() but all was working before correctly
in previous versions. So I lost data from my current session (wrong
session-id). There was always a $_POST or $_GET or $_COOKIE available
with the session-name and session-id, so session_start() was taken
this automatically. Now I have to execute session_id(..old id ..)
before session_start() and a session is started for the same id.

How to properly regenerate session ID's?

I have built a session library, and I am having a very random bug (I don't really know how to unit test this, so I just filled everything with log messages and waited till it happened again) that translates into a user being logged out, due to a session ID mismatch.
The flow of the application goes like this:
A request with a valid session ID is made
Session data is found for that session ID in the DB
The 'last activity' happens to be old, so it is regenerated and updated in the DB
The new session ID is sent in the response (as a cookie)
This works fine almost always, but sometimes the next request fails to match the session ID, because (this is my guess) it was sent after we updated the database (in the previous request, which was still running), but before the response with the new cookie came in.
Did I misunderstand the concept of regenerating a session ID? I'm regenerating session ID's only for security reasons, so someone that chose to be logged in for a year, still has his session ID changed from time to time.
One option would be to keep multiple session ids per user, but put expiry times on them - when it's time to regenerate a session id, add the new one, and put an expiry time on the old one equal to some reasonable period of time (a minute, perhaps). Keep accepting the old one in addition to the new one until the old one expires.
I assume you're using session_set_save_handler(), right..? If so, try doing the following:
session_regenerate_id($delete_old_session = true);
session_write_close();
Or even:
session_regenerate_id($delete_old_session = false);
session_write_close();
Calling session_write_close() should effectively save the new session data. You only have to pay attention when you call this (usually before privilege changes > redirects), since it ends the session.
End the current session and store
session data.
Session data is usually stored after
your script terminated without the
need to call session_write_close(),
but as session data is locked to
prevent concurrent writes only one
script may operate on a session at any
time.

What are session_id, session_regenerate_id and session_name used for?

ok im a newbie on sessions lets imagine that we have a little login site,
heres a logic
login
if password right = use $_SESSION[isaloginuser] = 1
check session to see menus with if $_SESSION[isaloginuser] = 1
show the menus
the user want to logoff
unset session
destroy session system
what it use
session_register
session_destroy
session_unset
session_start
where does the session_id & the session_regenerate or session_name goes in ?
at php site it says
session_id() is used to get or set the
session id for the current session.
i still just dont get it, why do we need them anyway ? in real environment what does it do ?
No, you don’t need to use them. In general all you need is
session_start to start the session handling, and
session_destroy to destroy the stored session data (this does not modify $_SESSION), and
session_unset to reset the $_SESSION variable (but you can also do $_SESSION = array()).
session_id and session_name are to get and set the current session ID and session ID name (default is PHPSESSID). session_regenerate_id can be used to regenerate/change the session ID of the current session. This might be useful if, for example, you want to refresh the session ID every 10 minutes or after changing the state of authenticity of a user associated with a session.
session_regenerate_id() is used in order to prevent session fixation.
Session fixation means the following: You visit a website and examine your session ID. Then you manipulate another user into visiting the site using your session ID, and signing in. Now you're signed in as that user and have his privileges, because you're both using the same session.
To prevent this, give the user a new session ID using session_regenerate_id() when he successfully signs in. Now only he has the session ID, and your old session ID is no longer valid.
session_register() is depreciated in 5.3, I would suggest against using. Instead just use
$_SESSION['varname'] = "value";
session_id it just used if you want to get the session id for storing in a database, this is not "necessary" for use. session_name, just sets a name, this is not necessary. The regenerate is if you want to do a new id, this is also not necessary unless your application needs it, for a login session, I highly doubt you will use it.
The others, I hope you understand what they do (ie the unset / destroy). But hope that gives some insight.
Session IDs are the identifier for the session. The way a server stores data about a client is in a cookie. This cookie is sent with each HTTP request to the server by that client. PHP sets a cookie to be a random string token. This token identifies the client and relates it to a set of key-value pairs. The idea of a session variable is that cookies can be easily tampered with. Session IDs, however, being random strings, are hard to duplicate and thus add security.
I usually use session_id() when creating shopping baskets so I can track what that user has added then once I have got a response back from the payment gateway that the payment was successful, I then session_regenerate() so that when they are back on to my website their previous baskets are not visible and to me its like a new user has "entered" the shop.

Cookie and session in "remember me" feature

I have never wanted to allow a user to stay logged in for any length of time so I never saw a use for a "remember me" feature. I started thinking about how it's done though and would like some clarification.
I'm currently storing my sessions in a database. What has always perplexed me was how, even though I do not explicitly set a cookie, one is placed in my browser. I'm a little confused because a session is a session and a cookie is a cookie. I don't see how a session sets a cookie.
I'd also like to know if, simply setting another session variable in the session array to keep the user logged in, would be sufficient or would I still need to set a cookie?
In order to pull the session data back from your database a key is needed. This is called the Session ID.
The session ID needs to be stored somewhere. Either as part of the URL string that the client posts back or, more commonly, in a cookie on the client. When the request is posted, session reads the value from the cookie and knows which record to pull back from session storage.
This happens automatically.
The only reason to use session is if the data you want to keep is greater than 4KB (browser limitations); or if the time required to pull the data from your server is greater than reading it from session storage.
If the amount of data you are storing is less than 4KB I would highly recommend you just set that in the cookie to begin with. I generally store things like the user id, user first name, and a couple other attributes. Bear in mind that it is trivial to inspect a cookies value, so this information should be encrypted prior to going to the client.
Another thing is if the query time to pull the data you need from the original source is small, then elect to do that instead of placing it in session. That way you only get it when you actually need it instead of with every single page load.
What has always perplexed me was how, even though I do not explicitly set a cookie, one is placed in my browser.
A session handler has to identify which session belongs to which user.
The vast majority of session libraries do this by setting a cookie.
(Is) setting another session variable in the session array to keep the user logged in would be sufficient or would I still need to set a cookie?
Most session libraries set session cookies. These are cookies without a specified expiry time. They expire when the browser closes and are not sufficient to implement a "Remember Me" feature (which is expected to persist across browser restarts, so must have an explicit expiry time).
Explaining the relationship between Cookie and Session:
PHP uses Cookie to uniquely identify the session for each user. That's the only more reliable way because cookie is sent each time you request a file from the server. Using the token in the cookie, which is also the Session identifier, PHP will look up the tmp directory to see if the session exists. If the session exists, the variables are loaded from the correct file and you will be able to access the variables on that session.
Therefore, cookies store the session identifier which is required to identify which user uses which session. This is also how Session Hijacking come about, when people can change the session identifying cookie to use another person's session identifier.
The underlying PHP session implementation sets the cookie. You can alter this and have the session ID value passed in the query string, but I don't recommend it. You don't use the cookie, PHP does. It references the session ID value stored in the cookie to perform lookups to session data.
I'd also like to know, if simply setting another session variable in the session array to keep the user logged in would be sufficient or would I still need to set a cookie?
As soon as the user closes the browser, the session is killed and the cookie is deleted. I don't believe any mechanism exits to persist the session value, and for good reason.

Categories