So my goal here is to manage the users through session id, so to do that
Check clients cookie if there is a old session id, if not ask server for a new one and save in clients cookie, else take the id and request the server to resume a session with that id.
Code:
session_id($_POST["SESSID"]);
session_start();
2.use the session id in every request to fetch users data.
but i have two concerns:
isnt it unsecure to allow the client to provide a session id for the server? wont that open the application for abuse, where people will try guess others users session id?
wont the server lose the control of which session are expired? as long the client have the old session id , they can use it forever ?
EDIT: a possible solution:
So to adress my concerns, i modifed the code, to set a an expiration date to every session id, and if the old session ID is expired then the server sets a new one for the client, like the following:
session_id($_POST['SESSID']);
session_start();
if( isset($_SESSION['expires']) && $_SESSION['expires'] > time()){
//use old session
}else{
session_unset();
session_destroy();
session_start();
session_regenerate_id(true);
$_SESSION['expires'] = date(strtotime("+1 hour"));
// use new session
}
This vulnerability even has a name. :) It's called session fixation.
Edit:
To avoid session fixation and related session vulnerabilities, you should
not assign sessions to anonymous users (sessions take resources)
whenever privilege levels change, and most importantly, when a user logs in, assign a new session id (if there was already one, reassign a new one)
always generate session ids on the server, never take a session id from a client
use the built in session management features (as opposed to things like generating your own session id)
use a reasonable session timeout, both sliding and absolute, depending on your business case
Note that this is not a comprehensive list, and it is in no particular order.
Related
A very trivial question, but it is a thought that came to me and I don't know if it can be pertinent or not, if for example in the login page, or any other page, we initialize the $_SESSION ['name_session']; and in the logout phase we are going to destroy them, what happens if several users simultaneously use a web portal.
I explain better that we have two users:
user1: enter the portal and the $_SESSION begins
Meanwhile
User2: he also connects
if user1 closes the $_SESSION, could it happen that even user2 will log out?
If, yes, you start the $_SESSION, with the user id it might be a good thing, so would the $_SESSIONs all have unique keys?
PHP sessions are connected to a specific browser session. Each client user gets their own session, and changes made to one session have no effect on other clients.
This is done using a cookie that's sent to the browser. When you start a session, it creates a random session ID, and this is set as the PHPSESSID cookie. When the browser sends back this cookie, it allows PHP to find the corresponding session data.
The session is not shared. Each user (browser / client) has it's own session. A cookie is used to track the individual sessions, as Dharman said. Anything you store in $_SESSION is stored for that individual user and is retrieved again using the session id from the cookie in the next request of that client.
By default, it is saved in session cache (OPcache) and it is not necessary to add the user's id, php takes care of that.
I want to add a "close other active sessions" button to my PHP web app.
I'm thinking of tracking (userid,sessionid,expiration) on a MySQL table and kill the sessions the following way:
$currentsessionid=session_id();
foreach($othersessions as $session){
sessionid($session['sessionid']);
session_start();
session_destroy();
}
mysql_query("DELETE FROM sessions WHERE userid = $currentuserid AND sessionid <> $currentsessionid");
session_id($currentsessionid);
session_start();
The table would also be updated after each session_start() if the user is logged, removing expired entries.
Expired entries are removed every time a user logs in.
Is this the proper approach? Any suggestions?
In PHP the sessions are normally isolated. You need to create your own session handler and write session (plus some extra tracking information) into the database so this become more easy to manage.
For example, like you have in your question, the userid. You then can search for sessions of a specific user.
Another field you should have is a timestamp so that you can let sessions expire, e.g. if older than X hours, you throw them away.
You can - if you like - also take a look if a user has got an existing session and import the old session. However this can have security implications. You need to think about what happens when an attacker logs on instead of the real user.
Can an attacker even throw the valid user out of the system then? That should be prevented.
Also take into consideration that you can take over the session data of a previous session under a new session ID. That is similar to session_regenerate_id(), a login should always regenerate the session id, as well as the logout and other, important steps (e.g. re-authentication before changing the email-address).
Is there a way that I can initiate a persistent session in PHP without the placement of a session cookie? Are there other ways of maintaining a session across pages, such as an IP address-based solution?
My reason for asking is, is that although most users have cookies on, I want to see if there's a way for a login system to work for those with it disabled (even though I think disabling cookies is just unnecessary paranoia, personally).
I don't think it's too much to ask your users to enable cookies. I find it silly when people turn them off entirely.
Otherwise, you can set your session.use_only_cookies to "0" to force the appendage of a session ID to URLs within your php. This approach, however, has several draw backs. Mainly that of keeping the state within the URL, as opposed to the Cookie header. If a user were to copy and paste the URL of the page they were on, and someone else were to click on it, they would both be using the same session.
<?php
ini_set("session.use_cookies", 0);
ini_set("session.use_only_cookies", 0);
ini_set("session.use_trans_sid", 1);
ini_set("session.cache_limiter", "");
session_start();
You can set the ini-Value of session.use_trans_sid to true in order to activate appending the session id to every URL. Have a look at this.
For security purposes you should then limit the session to the IP that created the session. This is not perfectly secure though, as someone with the same IP (behind a proxy e.g.) could reuse that very same session.
You can work with session IDs in URLs, and disabling cookies with:
ini_set('session.use_cookies', 0);
ini_set('session.use_only_cookies', 0);
ini_set('session.use_trans_sid', 1);
session_start();
// IP check
if($_SESSION['ip_check'] != $_SERVER['REMOTE_ADDR']){
session_regenerate_id();
session_destroy();
session_start();
}
$_SESSION['ip_check'] = $_SERVER['REMOTE_ADDR'];
// session stuff
Note: it's highly discougared to use session IDs in URLs. IP addresses can change when travelling around with a wireless card and proxy servers have the same IP address. It's easily broken when clicking 'an old URL' (with the old session ID).
You may also be interested in creating your own session handling function (in conjuction with a database). You would ignore the session ID, and bind it to the IP address. (see examples in http://php.net/manual/en/function.session-set-save-handler.php)
References:
http://php.net/manual/en/session.configuration.php
You could create a database record or temporary file and check $_SERVER vars against the request on every page load. It's a security risk, but with enough variables (have a look at the list here) you may feel you've gotten the chance of hijack down to an acceptable level; only you know how secure your app needs to be.
You can save session id per IP in the database:
Create a mysql table with three fields: session_id, ip and unique temp key (for logged users) or any other condition you like. Then turn off session cookies and use_trans_sid.
then make a code to manage session behavior based on this new table!
after session_start() save session_id in the table and later receive it from table (by IP and any other condition) and then call
session_id($in_table_session_id);
for more information and complete guide see: https://gist.github.com/mimrahe/77415f4a9e238c313bbe8c42f8a6b7fe
If I wanted to do that then I would add the session id in the HTML code as a comment tag and use and configure the PHP code to use that session id which is included in the HTML code. I think it will be more relevant to do that instead of doing it with user IP or adding the session id in the URL.
The correct answer on this is NO. Using any combination of variables besides a cookie is insecure.
Think about it: when a user FIRST requests a page, the server is sending the page along with a unique value saying "HTTP is stateless, keep this so I know it's 'you' next time you call". That means, that person, in that browser (regardless of tab), running at that time, has a unique token.
If and only if they've logged in successfully, that token can now be tied to a session on the server side. Tokens are supposed to be so long and random that nobody could guess one in time.
Multiple browsers could be using the same IP address. Multiple people could have the EXACT same user agent. A cookie is the only storage system that works.
There's actually one more way, and that is to add the unique token to every single link back to the server as well as all AJAX calls, like ?PHPSESSID=my-unique-token-189481958 - but that's a pain to code.
You can also login without Cookies only by Session Id and Time, but you have to write them both in your Database direct after Successful Login.
I have in index.php something like this that will always generate a new session id
based on time and the old session id if conditions are not verified.
if ($_SESSION['id'] != $row['session'] || time() > $row['sessiontime']) {
session_destroy();
session_start();
session_regenerate_id();
}
$_SESSION['id'] = session_id();
I use 2 variables in database for id and time.
And in login window I read the Session id from $_SESSION['id'] variable, then I increment the time and send both to database.
I have set up a login system that checks a mysql db validating username,hashed password, and a banned column (0 means not banned and is the default value, 1 means banned). if there banned they obviously cannot loggin.
The problem is i'm new to php and having a hell of a time trying to figure out how to log out a user who is currently logged in. As it stands now my cookie will last for 2weeks, and even if i ban a user, their session will stay active thus they will have acess for 2weeks or less.
How can i force a user to reauthenticate, without penalizing the masses.
Your server knows what cookie is associated with each user. Why not just delete that cookie from its "current sessions" table?
If the cookie is just "username, who is logged in", you have a real problem, because instead of a magic number, the cookie contains real information, and it becomes trivial to forge. Then a malicious user could simply create a cookie saying "I am [admin], and I am logged in", and that's obviously a much larger problem. So if you can't just delete the session cookie from the "known cookies" table to solve this problem, you have a bigger problem to worry about.
If you are doing your authentication system completely on your own (kudos on that, BTW) you merely need to unset the session value that contains their authenticated status. So, if you used:
<?php
session_start();
if(isset($_SESSION['isloggedin']) && isBannedUser())
{
session_unset();
session_destroy();
}
?>
The pseudo-code above calls to a fictitious function called isBannedUser() to determine if they are banned or not. If they are, in my example above I call session_unset() to unset all values stored within the $_SESSION and then session_destroy() to completely close the session. Some would probably argue that you may not need to unset if you're destroying, but I have just gotten into the habit of cleaning up all variables and values that I make in code.
This should be in every page so that you check if they're banned as frequently as possible. With the $_SESSION destroyed the user is, effectively, kicked out of any part of your website that requires authentication. You will need to implement supporting code in your login workflow that keeps a banned user from logging back in.
Hope this is helpful.
If you are storing the session data in a database, delete the row with their session information. Or, delete the file if using files. Then next page load, the login system shouldnt be able to verify their login information (since there's no info for that session), and prompt them to re-login.
On a file-based sessions system, maintain a counter somewhere which triggers a periodic check of the database for updates, something like:
<?php
session_start();
$_SESSION['hits_since_last_verification']++;
if ($_SESSION['hits_since_last_verification'] > 100) {
$banished = ... // get banishment flag from database
if ($banished) {
$_SESSION['loggedIn'] = FALSE;
}
}
?>
and then decide how long you'd like a banned user to be allowed to continue poking around the site until the session data is refreshed and they get booted.
Another option is an external script which runs through the session storage directory, loads each in turn, checks if the user's banned, and updates the session file as appropriate. But this would be painful on even a moderately busy system as you open/unserialize/check banishment/update/reserialize potentially thousands of session files every X minutes.
maybe you want to store the sessions in another table and delete it when you ban the user.
you know. check the table every time the user load a session and if the user isnt there. delete the cookie and destroy the session (sending him to the index of your site)
You can store the userID in the session and on each request, you check if he's banned (SQL query). If true, you destroy his session so he's forced to reauthenticate. Which fails of course because he's banned.
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.