Does anyone know how PHP maps session IDs to $_SESSION arrays? In other words, given session ID x, where does PHP pull the values from to populate the $_SESSION array?
And given a session ID and the url it came from, is there any possibility of someone being able to gain access to the values in the $_SESSION array?
By default, PHP uses the files session handler. These files are stored based on the session.save_path setting, but defaults to the system's temp directory (a highly insecure location, consider changing it)
This session handler stores each session as a serialized PHP array in a file named with the session ID.
If you can find out a session ID prior to it being cleaned up by the session garbage collection routine, it can be hijacked, as PHP does not internally do any sanity checks. You may wish to do your own by storing the user's IP address in the session and comparing it to their current IP, clearing the session if they don't match.
session.gc_maxlifetime controls how many seconds a session will be considered valid. After this point, the session has a small chance of being deleted every time a request occurs. Default is 1440 seconds (or 24 minutes).
By default, this chance is 1%, but can be altered by adjusting the session.gc_probability and session.gc_divisor values (they default to 1 and 100 respectively).
There are other session handlers as well, such as the ones included with the memcache or memcached extensions. There was once one based on the libmm shared memory library, but I believe that has been discontinued.
Session info is stored on server filesystem. There's configuration parameter session.save_path in php.ini. Some info about sessions security is given here: http://www.php.net/manual/en/session.security.php
Session data is usually stored in temporary files on disk (see the session.save_path setting) and the filename reflects the session ID.
In general, yes, if someone gets hold of another user's session ID and sends it along with his own request, he will gain access to that user's session. One way of solving this is to bind sessions to IP addresses and invalidate the session when a request arrives from a different address.
No, there is no possibility!
...unless your code or the code of any component used is insecure.
With the default implementation of sessions (which can be replaced by a custom one if needed) the data is stored in local files. Your server receives the session ID from the client in a cookie, finds the corresponding local file on your server and populates data into $_SESSION.
Gaining access to this data requires file-level access on the server, which is not impossible, unless your server is secure enough.
You can also write your own session handler to save the session to a database.
Also, if you want to make it harder to pin down the session ID, regenerate the session ID at strategic times (on privilege elevation, etc) -- or as often as you want.
Pass session_regenerate_id() the argument True to destroy the old session data.
Related
Lets say the client logs in successfully and the server ( Apache / PHP ) creates a session, where is stored the userid:
$_SESSION['userid'] = $UseridFromTheDB
What does this line exactly?
Stores the userid on server-side memory
Stores the userid on client-side cookie
Both 1. and 2.
I think the 3. is the correct, because I did not used any else code to make the session on server and make the cookie on client.
So as I said all I have to do to use $_SESSION global variable and it will make the magic for me. It will store the session variable in the memory on server-side and it will make the Set-Cookie header, so the userid will be stored on clien-side as a cookie.
So my question is, what if I modify the userid on client-side? For example if I see 100 as an userID and I will modify it to 101, then the next request will be made with userID 101, right?
The server will give me the content, which belongs to 101 userID?
It stores the session both in the server-side memory and client-side cookie.
No. The session information (e.g. all the variables) are stored in a file on the server only by default. The cookie is called PHPSESSID and is merely a unique ID that points to one of the files on the server. The name of this cookie can be changed by changing the session.name option in PHP's runtime configuration, so it may have a different name per website.
These files are stored in the tmp/ directoy of the server by default. Unless you have access to the folder that these files are stored in (a massive security flaw), there is no way to get access to them.
When I create a PHP-file with the contents below:
<?php
session_start();
$_SESSION['userid'] = 1;
$_SESSION['username'] = 'user1';
It created a cookie in my browser with the name: PHPSESSID and this content:
11j9etj85pfnq36h15qb9mu60v
This corresponds with a file called sess_11j9etj85pfnq36h15qb9mu60v in the tmp/ folder of my XAMPP install. This file has the contents below, which as you can see contains the variables present in the $_SESSION global.
userid|i:1;username|s:5:"user1";
What if I modify the userid on client-side?
How? Unless the website has a major security flaw that allows you to execute PHP code, or does something ridiculous like setting the $_SESSION['userid'] based on a form input, you have no way to modify it.
You could copy the session ID from one browser's cookies to another, but this is a whole other issue and not related to the session security. It may not even work if the website checks the user-agent and IP-address of the connection and logs you out if they don't match the information that the session was originally started in.
For example if I see 100 as an userID and I will modify it to 101, then the next request will be made with userID 101, right?
No, since the session is not based on a variable within it. You would need to correctly guess a PHPSESSID to hijack another user's session. Again, unless the website has a major security flaw, there is no way for you to change variables in the $_SESSION superglobal. Most somewhat-modern web frameworks like Laravel encrypt the session cookie and make the length longer than the default length, making it even more impossible to guess one.
My questions:
session.gc_maxlifetime in php.ini: Does the session.gc_maxlifetime start from the session_start() point or the latest request to the server? (Assuming I have a few requests without a session_start() being called.)
What is the best practice to use the $_SESSION object so as to not waste precious RAM (automatically clear idle sessions in time)? Or is this something that happens automatically by the time mentioned in session.gc_maxlifetime?
How do I correctly check if a session has expired (as against a session which never got created)? Or are both the same? isset($_SESSION['any_variable']) === FALSE
Assuming I don't have control over php.ini, how do I increase session.gc_maxlifetime?
session_start(): If a session has "timed out", calling session_start will always start a session with the previous variables unavailable(a brand new session). Is that correct?
Good question! I would assume that the default filesystem session handler would go off last access but not all filesystems support an atime timestamp. I'll see what I can find out on that front.
Sessions are by default stored as files on disc. They only take memory when loaded. Unless you've built a custom session handler that stores sessions in a RAM disc or in a memcache server or similar, or unless you're storing a huge amount of state in the user's session I doubt memory use will be a major concern.
When session_start() is called the previous session data is loaded into PHP. If the session has expired then there will be no session data to load and a new empty session will be created. So yeah, if you check for the existence of a variable in $_SESSION that you're expecting to always be there then you can use that to determine if the user's session has expired (but only after session_start() was called).
Simply set gc_max_lifetime to how long you want sessions to last in seconds. 600 is 10 minutes, 86400 is one day, etc.
Yes (with some caveats, see below).
There are a few things you need to be aware of with sessions though. First is that there's two components to a session: A server side state record that holds all the data stored in the session, and a client side token that PHP uses to associate a particular user with a particular state record. Normally the client side token is a cookie. Cookies have their own expiration date, so it's possible that the session can expire before the session state is due to do so. In that case the user will stop sending the token and the session state is effectively lost. If you're adjusting how long a session lasts you need to set both the server side state expiration time and the client side cookie expiration time.
As for stale state, the session garbage collection system doesn't always run every time session_start() is called. If it was the overhead would be crippling to a big PHP site with a lot of sessions. There are configuration options that specify the probability that the GC will run on any given invocation of session_start (I believes it defaults to 1%). If it doesn't run then a stale session record may still be treated as valid and used to populate $_SESSION. It probably won't have a serious effect on your system but it's something you need to bear in mind.
I want to have sessions persist the browser closing
So I used
session_set_cookie_params(86400 * 60, '/', 'my.domain.com', true, true);
to send a persistent cookie to the client (also with the secure flag as this is a SSL site)
which is valid for 2 months.
However, I see that after x minutes of inactivity the session variables are cleared on the server.
How can I avoid that? Essentially, I want the session variables to be stored until the cookie
becomes invalid
Thanks
Set the session.gc_maxlifetime configuration property.
The documentation is rather sparse when it comes to acceptable values for it, but I wouldn't want to go as high as two months.
You'd usually be better off storing the important data in a database, and adding it to a session when one is created with a remember me cookie.
Leave sessions for actual sessions.
With sessions you are looking at two things. The time until garbage collection cleans up the session on the server, and the time until the cookie expires.
You only changed the cookie expiration, the session will still get cleaned up. However extending the session is not a great way to solve this. Your code could change and you may end up with users having a broken session. You may need to use some sort of shared session storage like memcached that will delete the storage after a certain max time anyway.
So the way to solve this is to generate a unique one time cookie that can be used as an alternative login key. This key will allow a user to login similar to a username/password. Once its used, a new one gets regenerated.
Session variables will persist as commented below, but unless you change their default behavior, they expire when the session ends (i.e. when the browser is closed).
For what you're trying to accomplish, you should store your values in $_COOKIE variables, not $_SESSION variables.
See this article: http://buildinternet.com/2010/07/when-to-use-_session-vs-_cookie/
I'm setting up a script that my local pub will use to show users slide shows of images, menus, etc. My URL will accept a key(uuid), from which my script will query the database for the content associated with the key based on a company_id. The site will then just rotate through images via javascript or jquery.
Before serving out the content, I would like to make sure that the session or user is authenticated meaning that there is a valid company_id associated.
I've always used $_SESSION variables for web sessions. Since there will be no real need to time out a session, would there be any flags I can set in php.ini to never time out? Or would it be more beneficial to use cookies for this type of work?
Thanks.
You are probably better off using a cookie to store a login token for the user with a distant expiry date, so they are auto-logged in. Preserving $_SESSION indefinitely would cause session files to pile up on your server wasting resources on the filesystem. Instead, a cookie can hold some token (non-guessable value) that is associated with the user in your database. Basic information can be retrieved from the database then when the user returns.
When you call session_start() the script will try and set a cookie in the users browser containing the session id, there is no need to manually set one holding a "non-guessable value" since that is what the session id is supposed to be anyway.
You can change session.cookie-lifetime in the ini file (maybe even with ini_set()) to prevent the cookie timing out at the end of the session.
Preserving $_SESSION will not cause session files to pile up indefinitely. By keeping the session alive the same file will be re-used over and over again (since it is named after the session id), and PHPs built in session garbage collector will clear up dead sessions anyway.
While in general it is a bad idea to make sessions last forever, since it's your local pub, I doubt anyone is going to try and hijack their session. (and even if they did, all they'd get is what's for sunday lunch, right?) :)
Edit:
You could also periodically regenerate the session id, to add a bit more security.
I know that sessions are server side, so, it is possible to save a session even if the browser is closed?
For example save a session for one day.
Please do not suggest "cookies", in this case must be implemented sessions.
thanks
They are saved already (see your php.ini file for the session path)... In fact, the real issue lies in garbage collecting them.
If you want to store them longer, edit your php.ini file or, define a custom session handler:
http://www.php.net/manual/en/function.session-set-save-handler.php
session_set_cookie_params I think is what you are looking for. If you are storing the session in a cookie, this will allow you to set the lifetime of that cookie. So the user can come back anytime within that time frame and still have their original session.
Side Note
Give this a read for more about session lifetimes etc.
How do I expire a PHP session after 30 minutes?
php_value session.gc_maxlifetime 86400
You can set the above in .htaccess or modify session.gc_maxlifetime in php.ini
This defines how long PHP will have a session file for the user on the server before garbage collection (the example above will allow the server to maintain the sessions for 1 day), however sessions generally do rely on a session id cookie so if the browser is reset or clears the cookie the user won't re-attach to their web session (you are actually setting a session ID cookie to use sessions in most cases even if you don't realise it.)
You can create a database and store there the sessions and on client side just store $_SESSION['id'] wich is the id of the session in the database. But this will become a headache when you will have to store more and more variables in the session.
Like Gumbo said, pass it in the URL. But how I like to solve this is, instead of passing the SESSION_ID through the Url, just make it a hash, or encoded data.
Then whenever this user comes to your page. you can check in your headers if this hash/encoded-data is still in the valid time frame, and if this 'anonymous' user has permissions for thay zone.
THE DOWNSIDE: If this user passes around this link, anyone could access the data
THE UPSIDE: Extremely portable, and easy to implement
Store the SESSION_ID in a database bound to the users IP. whenever this user logs back in, start the session via setting the SESSION_ID with session_id
THE DOWNSIDE: A lot more work, and if the users ISP changes their generated IP regularly this won't work
THE UPSIDE: Even if he erases the SESSION_ID cookie you will be able to continue the session
there are many ways to do this but beign an artisan you could:
make an script that save each session for your users inside a file
OR
go to PHP.ini and change the session life time
OR
use the session_set_save_handler function more info here