I am using Facebook's PHP SDK for validating users to leave comments and it works quite well. Once, validated, I store the user information in a session variable, but first call session_regenerate_id() and then reload the page. When the page reloads, the old session data is still available, including the Facebook SDK state variable, however, the session variable I added is not available. The following is a snippet of the code:
session_regenerate_id();
$_SESSION[...] = ...;
header('Location: ...');
die();
If I take out the session_regenerate_id() then everything works perfectly. Any ideas what I am doing wrong?
EDIT
If I log session_id() every page load, I see that session_regenerate_id() generates a new id and the session contains everything I expect. However, when the page reload occurs, the session id is the previous session id and not the new one, hence I cannot access the new session variables. Why would this happen?
After a lot of logging and scanning the headers being sent and received, I determined that when the initial session was created, the domain used for the cookie was: .domain.com (without the www). However, session_regenerate_id() was setting the domain for the cookie to: www.domain.com. When the browser made a determination of which to send, it always sent the original one, so the session used was always the old one. Once I manually deleted that cookie, everything worked fine.
To ensure this sort of thing doesn't happen again, I added the following before starting my session:
session_set_cookie_params(0, '/', $_SERVER['SERVER_NAME'], true, true);
What is odd, the .htaccess file enforces www.domain.com for consistency, so I am not sure why the initial cookie's domain was set the way it was.
Related
I have a session formed the following way:
function sec_session_start() {
$session_name = 'primary_session';
$secure = false;
$httponly = true;
if (ini_set('session.use_only_cookies', 1) === FALSE) {
header("Location: /error?e=1");
exit();
}
$cookieParams = session_get_cookie_params();
session_set_cookie_params(3600,$cookieParams["path"],$cookieParams["domain"],$secure,$httponly);
session_name($session_name);
session_start();
session_regenerate_id(true);
}
I use this on all my page by adding
sec_session_start(); on my index page, which requires correct files depending on what page I am accessing.
It works perfectly fine with slow navigation.
However, when rapid navigational clicks occur, for some reason it unchecked, and the user is logged out.
How come?
This is the button I press rapidly. NOTE: It also changes the page from www.example.com to www.example.com/users, and then just repeats www.example.com/users until session is broken.
And this is the result after about, 2-3 rapid clicks. Works fine when pressed 1-2 times a second, max.
I have tried not using it as a function, and putting it on the absolutt TOP of the page without success.
The error seems to be session_regenerate(true).
This command generates a new session id. The parameter will delete the old session file if it is set to true. In this code it is set to true, so the session is created an started and then directly closed and deleted.
I think it appears only a few times because the command is called after session_start() was called and the output already started.
Try changing the parameter to false.
For the right use of session_regenerate() look into this question.
You appear to be discarding the old session ID on every page load. This is unnecessary, inefficient, and causes breakage.
If you navigate twice in quick succession what can happen here is:
the first request hits the server and starts executing your PHP, causing session_regenerate_id(true) to destroy the old session
this will cause the response from the PHP script to include a Set-Cookie: sessionid=something header, asking the browser to update its cookie to point to the new session
but the browser hasn't received the response from the script quite yet
you click a second time
the browser discards the existing request. Any Set-Cookie header isn't going to get listened to now
the browser makes a new request to your server. The browser doesn't know anything about a new session, so it includes the old session cookie
your script sees the old session cookie, which points to nothing, so user has to start a new session which isn't logged in
If you have an anti-Cross-Site-Request-Forgery system based on storing a synchroniser token in the session, then regenerating the session ID on every page load will also make any forms you use inoperable when the browser has multiple tabs open on the site at once, or when the user navigates with the Back button.
You should only session_regenerate_id when the authentication associated with a session is changed (primarily, when the user logs in).
Changing session IDs does not prevent session fixation; it is only a mitigation for when session fixation has already occurred through some other means (eg a vulnerable app on a neighbour subdomain injects a cookie into the shared parent domain).
If you didn't change the session ID, then an attacker who had already gained session fixation could get a full session hijack, by giving you a session ID she already generated and knows, and letting you log in using that session, upgrading it to an authenticated session. When you change the session ID on auth boundaries that isn't possible; the worst she can do now is push you into a session in which you are unexpectedly logged in as her. Which isn't ideal, but generally this constitutes a much less damaging attack.
I have an application where the login and logout works correctly. Once the user logs out, and tries to access a page he needs authentication for, he is redirected to the login screen.
Where my problem lies is. If while I am logged in, if I copy the cookie values and save them on a file. After logout, I alter the cookie and add the same values, I get logged back in into the application as the same user.
On logout I have written a function that loops over all the cookies and deletes them.
My understanding is that cookies are both on the client and also on the server side. So if the cookies are getting deleted, they are getting deleted on both the sides and that the server would not recognize them after they have been cleared, even if the browser sends them back again(apparently that is not the case, i think).
The reason why I am doing this is because this is one of the points raised by our security auditor, and I need to get a way to fix this hole. (At this point doing https is not feasible)
I'd be happy if someone can give me pointers on how I can clear out the cookies on the server side as well, so, when the next time someone hits the server with the same cookie, it does not accept it as a valid cookie.
Edit:
I am using codeigniter sessions and tank_auth as the authentication library. At logout, the library itself calls
$this->ci->session->sess_destroy();
to be extra sure, I tried the following after a few attempts :
session_start();
session_unset();
session_destroy();
session_write_close();
setcookie(session_name(),'',0,'/');
session_regenerate_id(true);
My regular logout works, and if I try to access the page directly it does not open.
But if while I am logged in, I take my cookie, save it somewhere -- log-out successfully and replace the cookie with my older one, I get right back into the session.
Is there a way to stop this behavior -- Where the server side will not entertain a session after it has been destroyed. I also made sure that my server and php are on the same timezone (setting it with date_default_timezone_set).
Cookies are not stored on the server at all. Those are stored in the browser and then sent to the server in the request headers. You can easily find software and plugins for browsers that allow you to create/edit/delete cookies. For that reason you should never store sensitive information in cookies. Essentially what you want to do is store the user data in a session and then store the session name in a cookie. Usually this is done automatically in php when you use the function session_start().
If you are using Codeigniter, the php session functions are wrapped in a CI session library that is auto loaded on each page load. So instead of storing data in $_COOKIE you will want to get/set your data via the userdata method in the session library:
//in your controller
//save session data
$userdata = array(
"isLoggedIn"=>true,
"username"=>$_POST['username']
);
$this->session->set_userdata($userdata);
//get session data later
$isLoggedIn = $this->session->userdata("isLoggedIn");
if(!$isLoggedIn){
//if the user is not logged in, destroy the session and send to the login screen
$this->session->sess_destroy();
redirect("/");
}
Note that the code above is not tested and is only supposed to give you an idea on where to go. If the session methods aren't working for you, you may need to load the library in manually:
//in the __construct method of your controller:
$this->load->library("session");
You can find more information here:
http://ellislab.com/codeigniter/user-guide/libraries/sessions.html
and here:
http://www.php.net/manual/en/book.session.php
Thanks for you answers guys.
This is what I figured, later. I am not sure what was causing this but the sessions were not getting invalidated after trying everything. I moved the sessions on codeigniter to the database. Then the logouts started working correctly, where after logout if the 'stolen'/'saved' cookie was put in the browser again it would Not log the user back in.
So, thats what solved it.
I use OAuth to authenticate at an external website. Everything is okay but the session variable misses after redirecting from external websites.
Summary:
I store a session var in my website then go to login page of other website. After logging in and confirming, it redirects to my callback, when I check the previous session var, it misses! How to fix it?
I tried to call session_start() everywhere I use session but it doesn't work. Of course I enabled session in "php.ini" and enabled cookie in browser. :) I debugged but can't find the reason out.
Update:
After storing my session var, I do a request like this:
http://mixi.jp/connect_authorize.pl?oauth_callback=http%3A%2F%2Fmypage.com%2Fcallback.php&oauth_token=fjdklsfjlksd
Note the oauth_callback, it is the redirect URL. I don't know what mixi.jp use to redirect.
Make sure your site's domain is 100% identical before and after the redirection.
Note that
www.yoursite.com
and
yoursite.com
are two different sites cookie-wise.
The session id is stored in a cookie. The cookie is send in every page of the domain you registered in. Whe you jump to another domain, your cookie with the session id is not send. You must pass the session id to your new domain and then create a new cookie in this domain with the session id.
header('Location:redirect.php?session=' . sessionĀ_id());
And then in the redirected page restore the session
<?php
session_id($_GET['session']);
session_start();
User fills in username and password.
If it's correct, the page loads some information such as user_id to a session variable.
The script makes a header('Location') redirect.
Somehow the next page doesn't recognize the session... how come?
The redirection is to the same domain, and all pages have session_start();
And I found it more likely to happen in IE than in FF... strange.
Is it possible that cookies aren't enabled?
In order to be able to associate session variables with a specific client instance (ie. how session variables can be used on your browser and my browser at the same time without getting into a conflict), a "session ID" (or "SID") is generated per session. This ID is stored on the server, as well as on the client, usually in the form of a cookie. However, if cookies are not enabled, the session ID is passed along as part of the query string of the URL in each request so that the server can know what session ID belongs to the client.
When you redirect by a header() call, PHP does not automatically insert the SID into the new request, so you will need to append it yourself, in the form of:
header("Location: my_url.com/my_page.php?" . SID)
where SID is a constant defined by PHP that contains the necessary part of the query string (equivalent to session_name() . '=' . session_id(), if a session ID exists).
See Passing the Session ID for more details.
I just had a similar issue, the solution was to simply add an exit(); instruction under the header(..) redirection.
Two thoughts:
Is session_start() located at the top of the scripts, before anything is sent to the browser?
Is the domain exactly the same? www.mydomain.com re-directing to mydomain.com would lead to the problem you describe.
header("Location: my_url.com/my_page.php?" . SID)
exit();
It only worked after I added exit() below the header();
The WordPress documentation states that cookies will be cleared if the user's password is changed. That will kill the session, regardless of whether a redirect happens. So long as you can prevent the cookies from being cleared (and an exit() may do that, as suggested in other answers) than the session should remain.
Note: If current user's password is being updated, then the cookies
will be cleared!
http://codex.wordpress.org/Function_Reference/wp_update_user
I had this problem today and have been searching for a way to fix it. I already had what everyone else has mentioned and could not find an answer anywhere.
Eventually I found the answer after watching my session variables with Firebug. I noticed that on the pages that the variables were being lost, the session Parameter:secure was being set to true for some reason unknown to me.
The fix was to set the secure parameter to false before the session was created.
I accomplished this using session_set_cookie_params. Something like this:
session_set_cookie_params([lifetime], [path], [domain], false, true);
I have 2 pages: login.php and index.php. Both pages start with
session_start();
When I set
$_SESSION['user'] = "name";
in login.php and than open index.php, my session object is empty. How come?
EDIT:
I found the problem: IE 7. I had to grand access to my domain. However, I thought a session is stored on the server, instead of the client? Than why do I have IE grand access to my domain? (http://www.pcwindowstips.com/2007/09/04/how-to-enable-cookies-in-internet-explorer-7/)
I thought a session is stored on the server, instead of the client? Than why do I have IE grant access to my domain? (http://www.pcwindowstips.com/2007/09/04/how-to-enable-cookies-in-internet-explorer-7/)
The way sessions work is that a session cookie is stored for the site, which contains your session ID. The only way the server knows who you are is when it reads the session ID cookie on every page load. All of the $_SESSION data is stored on the server for each user, but the cookie must be set for the server to know which $_SESSION data to retrieve.
This is also why you can essentially "become" another user if you obtain their session id cookie.
Internet Explorers have a stricter cookie policy than most other browsers. Check your session cookie parameters (see also session_get_cookie_params()) and try to replace the default values by explicit values where possible. Additionally you might send a [fake P3P policy](http://msdn.microsoft.com/en-us/library/ms537343(VS.85).aspx) to satisfy the Internet Explorers.
Perhaps this variable in php.ini is mapping to an existing path
session.save_path = "c:/wrong/path"
Here is something that happened to me that might shed light for someone. My session wasn't working properly. IE 8 and Firefox were losing the session information.
I included a file. That included file had an extra carriage return after the trailing &ques?>
That carriage return started the session. I put session_start after the include. BOOM.
Not much info here, I'll try to use my psychic powers.
After the user logs in, do you set the session var and then redirect the user to index.php using an http header? If so, I don't think the session cookie gets sent to the user. If that is the case, the solutions are:
call session_start() when the login form is initially displayed (not just after the user posts back to it); or:
display a "login successful!" message and then redirect with a meta-refresh, or just provide a link to index.php.
You can also try to dump the session ID on both pages, to see if you are somehow starting a new session:
echo 'Session ID is: ' . SID . "<br/>\n"
You need verify if the cookies are enabled and nothing ( this includes blank lines in the beginning or in the end of archive) sent to browser before you call session_start().