I have a website that use mercadopago payments (similar to PayPal, from South America).
When user finish payment and is redirected back to my site, I get a new session id and I am not able to read old one, also not able to read previously set cookies.
My problem is that I need cookie or session value to keep user logged in, if not, I need to ask user and password again and the client does not like that.
This is the code that I am using to set the cookies, with comments explaining my problem:
<?php
session_start();
include("db-connection.php");
if(isset($_SESSION["id_alumno"]))
{
$sid=session_id();
if(isset($_COOKIE["user_token"])){
//just for debbuging
//echo "user_token is a " . $_COOKIE["user_token"];
}else{
//set cookie and update same value in database
setcookie("user_token", $sid, time()+2*24*60*60);
$id_alumno=$_SESSION["id_alumno"];
$sql="UPDATE `alumno` SET `login_token` = '$sid', `login_creado` = NOW() WHERE `alumno`.`id` = '$id_alumno'";
$res=mysqli_query($link, $sql); //this connection values are send in a db-connection.php already included.
}
}else{
$cookie_value=$_COOKIE["user_token"]; // here is my problem, I can't access this value, checking cookie information using chrome and the plugin web developer, I get 2 PHPSESSID (old which was used to set cookie with user_token, and also the user token value, and also this new PHPSESSID)
if(isset($cookie_value)){
$sql="SELECT * FROM alumno where login_token='$cookie_value' and login_token!='no'";
$res=mysqli_query($link, $sql);
if($reg=mysqli_fetch_array($res))
{
//here I can login back the user
}//mysql query
}//if isset cookie value
}
?>
You're using session_start() with it's default options. As soon as you leave your site the session cookie expires.
Try example #3 from the manual:
<?php
// This sends a persistent cookie that lasts a day.
session_start([
'cookie_lifetime' => 86400,
]);
?>
This sends a persistent cookie that lasts a day.
See also: How do I create persistent sessions in PHP?
Related
i'm learning to use cookies in PHP. I was expecting that every time i set a cookie, the cookie and all of his variables are stored on the client site so i could use them again next time the user will visit the site. Anyway in the next example (a web application with a sign in option, i use cookies to store a unique string so i could implement "Remember me" option) i can access the id of the stored cookie but the variables data seem lost. Here is example of the code i use and screenshots of what i get.
Setting up a Cookie
if (isset($_POST['remember_me'])) {
$token=uniqid($_SESSION['id']);
$sql="UPDATE users SET token='$token' WHERE id='".$_SESSION['id']."'";
$conn->query($sql);
setcookie("remember_me", $token, time()+30*24*60*60*1000);
}
else{
setcookie("remember_me","",time()-1000);
}
User page
On the user page it just simply prints out the $_COOKIE and $_SESSION array.
<?php
echo "SESSION: ";
print_r($_SESSION);
?>
<br>
<?php
echo "COOKIE: ";
print_r($_COOKIE);
?>
Process:
First i delete all the cookies using the advice i found here:
how to delete all cookies of my website in php
Then log inside Log in screen (this form call a script that execute the code for setting a cookie i gave at the beginning, then redirect to the user-page) User page before closing
Close the browser and open it again directly at the user-page (without executing other scripts /localhost/MIAFormApp/script/db/HTML_PROBA/user-page.html.php User page after re-opening
What did i get wrong and why the cookies array after re-opening is empty?
EDIT:
The second time i open browser the script for seting the cookie is not executed. I just set the url to go to the user-page.php .
Examp:
/localhost/MIAFormApp/script/db/HTML_PROBA/user-page.html.php
Try deleting the else statement in your sample code - meaning go from:
This
if (isset($_POST['remember_me'])) {
$token=uniqid($_SESSION['id']);
$sql="UPDATE users SET token='$token' WHERE id='".$_SESSION['id']."'";
$conn->query($sql);
setcookie("remember_me", $token, time()+30*24*60*60*1000);
}
else{
setcookie("remember_me","",time()-1000);
}
To this
if (isset($_POST['remember_me'])) {
$token=uniqid($_SESSION['id']);
$sql="UPDATE users SET token='$token' WHERE id='".$_SESSION['id']."'";
$conn->query($sql);
setcookie("remember_me", $token, time()+30*24*60*60*1000);
}
When you re-open your browser, the if statement is going to check whether or not the POST variable remember_me was found. The only time that it will be found is when someone logs in because the login form is sending that information on form submit. In every other instance ( such as re-opening the browser), the else statement will be executed which isn't what you want. The reason being that setting an empty value on a cookie will delete said cookie.
This question already has answers here:
Can a user modify a PHP session?
(3 answers)
Closed 7 years ago.
I am developing my own application which requires user login. All users and passwords (encrypted) are stored in a database. When a user tries to login, then it search in the database the username and password. If all is ok, then I store username in $_SESSION["username"], user role (admin, author etc) in $_SESSION["role"] and user website in $_SESSION["website"] (I need website to be stored because the application is like "multisite" - my applicaton is hosted on client hosting but the administration is on my server).
I read this Can a user alter the value of $_SESSION in PHP? and I don't understand. Is this method secure (of storing data and if user is logged in) in a $_SESSION?
Can the user change the session content? (for example, if user is logged in and $_SESSION["website"] is "example.com", can the user change the session $_SESSION["website"] to "example.org" to ruin another website? If yes, how to avoid or what's the secure alternative of session?).
And please tell me what is session hijacking and how can this affect my site and also, how to make session_id dinamically to change?
Thank you so much!
$_SESSION is saved in the server, so the user cannot modify it ( Except the case of session hijacking)
Session() is server side as #kd0807 noted. For more info on Session Hijacking && Fixation:
http://phpsec.org/projects/guide/4.html
http://php.net/manual/en/session.security.php
Side note...
With the amount of variables I recommend an array for session['user'].
example....
$_SESSION['user'] => Array(
'userid'=> '123',
'username'=> 'some_joe',
'role' => 'customer', // user, customer, admin, moderator etc.
'website' => 'http://www.example.com'
);
// reading variables from array
$userid = $_SESSION['user']['userid'];
$username = $_SESSION['user']['username'];
// etc. etc.
Here are 3 very simplified functions I use.
// determine if session has started
Function HasSessionStarted() {
$result = false; // default to false
// Check if session has started
IF ((session_status() == PHP_SESSION_NONE) || (session_id() == '')) {
$result = true;
}
return $result;
}
// Set a session value
Function Set_Session($name, $value) {
/* #params value: can be a string or an array */
$new_session = HasSessionStarted(); // Check Session Status
IF ((isset($name)) && (isset($value))) {
IF ($new_session) { session_start(); }
$_SESSION[$name] = $value;
IF ($new_session) { session_write_close(); }
}
}
Function Unset_Session($name) {
$new_session = HasSessionStarted(); // Check Session Status
IF (isset($_SESSION[$name])) {
IF ($new_session) { session_start(); }
unset($_SESSION[$name]);
IF ($new_session) { session_write_close(); }
}
}
There is a cookie stored in the browser usually PHPSESSID which identifies which server session the user is using. If a user were able to steal it (this usually happens through XSS vulnerabilities) the user could potentially take control of another users session.
The session data itself is stored on the server and could only be modified if a user were somehow able to upload and execute a malicious script in the server
No, Until and unless the php code itself reveals the PHP session, which can be used to session stealing, and the session could not be changed from the user end until and unless the there is some functionality given by you yourself to change the session from the front end.
`$_SESSION` variables are stored in the server and hence cannot be modified by the user.
One of the best practices is that we must keep changing the session id from our end.
Thats why we use a function called session_regenerate_id().
This function that will replace the current session ID with a new one, and keep the current session information, so the use will not be logged out.
To answer your question in comment:
Whenever you start a session, server will send back a cookie which will contain the session id, the cookie name will be PHPSESSID which is the default name. You can also choose to change it. So this id is what that keeps changing when you use the session_regenerate_id function.
REASON WHY TO USE IT:
This mainly helps in preventing session fixation attacks.In this attack a malicious user will try to fix the session ID (SID) of another user. If he gets successful,the user will get all the access of the original user and will be able to do anything that the legitimate user can do.
So if you regenerate the session id the previous old session id will be no longer valid
You can get more info about session fixation IN OWASP WEBSITE
Can the user change the session content? (for example, if user is logged in and $_SESSION["username"] is "example.com", can the user change the session $_SESSION["username"] to "example.org" to ruin another website?
No. Sessions are stored on your server thus it would be impossible to directly change the session. On the other side, it all depends on the developer and how the interprets the client requests. For example, making
$_SESSION['last_website'] = isset($_SERVER['HTTP_REFERER'])
? $_SERVER['HTTP_REFERER']
: $_SERVER['REQUEST_URI'];
would eventually override the $_SESSION['last_website'].
Yes user cannot change session Variables...
if it hacked it can changed...
you need to get user id to change the $_SESSION["website"] in your current domain and use strict validation...
Otherwise they can hack it....
I can't seem to find a straightforward answer to this question. Is there a way in which I can force a logged in user to logout? My login system essentially just relies on a session containing the user's unique ID (which is stored in a mysql database). So essentially just...
if (isset($_SESSION['user_id'])) {
echo "You're logged in!";
} else {
echo "You need to login!";
}
But let's say I want to ban this user, well I can change their status to banned in my database but this won't do anything until the user logs out and attempts to log back in... So, how do I force this user to logout? Preferably without checking every single time they view a page whether or not their status has been switched to "banned" because that seems like unnecessary stress on my server. Any help is appreciated, thank you.
Either you need to check every time they load a page, or possibly look at an Ajax call at set intervals to check their status from the DB.
Then you can use session_destroy(); to end their session. This will destroy their entire session.
Otherwise you can use unset($_SESSION['user_id']); to unset a single session variable
Preferably without checking every single time they view a page whether or not their status has been switched to "banned" because that seems like unnecessary stress on my server.
Loading the user from the database on every page load, rather than storing a copy of the user in the session, is a perfectly reasonable solution. It also prevents the user from getting out of sync with the copy in the database (so that, for instance, you can change a user's properties or permissions without them having to log out and back in).
Try to put this on every page...
if (isset($_SESSION['user_id'])) {
$sql = "SELECT from tbl where status='banned' and user_id=$_SESSION['user_id'] ";
$query = mysql_query($sql);
if(!empty(mysql_num_rows($query))){ // found the banned user
//redirect to logout or
//session_destroy();
}
} else {
echo "You need to login!";
}
if the user is still logged in... check if his/her status is banned or not... if banned.. then logout
You can unset it.
unset($_SESSION['user_id'])
You could use Custom Session Handlers this way you have full control where and how the session data is stored on the server.
So you could store the session data for a particular user in a file called <user_id>.session for example. Then, to logout the user, just delete that file.
Ajax calls in an interval will put extra load on server. If you want real-time response to your actions(e.g. the user will be signed out right when you ban them from your system backend), then you should look into something like Server Push.
The idea is to keep a tunnel open from Server to Browser whenever a user is browsing your website, so that you can communicate with them from server-side too. If you want them to be banned, push a logout request and the process that in your page(i.e. force logout by unsetting session).
This worked for me am using pHP 5.4
include 'connect.php';
session_start();
if(session_destroy())
{
header("Location: login.php");
}
You can use session_save_path() to find the path where PHP saves the session files, and then delete them using unlink().
Once you delete the session file stored in the sever, the client side PHPSESSID cookie will no longer be valid for authentication and the user will be automatically be logger out of your application.
Please be very careful while using this approach, if the path in question turns out to be the global /tmp directory! There's bound to be other processes other than PHP storing temporary data there. If PHP has its own directory set aside for session data it should be fairly safe though.
There is a few ways to do this the best in my opinion based on security is:
NOTE: THIS IS REALLY ROUGH.... I know the syntax is wrong, its just for you to get an idea.
$con = mysql_connect("localhost","sampleuser","samplepass");
if (!$con)
{
$error = "Could not connect to server";
}
mysql_select_db("sampledb", $con);
$result = mysql_query("SELECT * FROM `sampletable` WHERE `username`='".$_SESSION['user_id']."'");
$userdeets = mysql_fetch_array($result);
if($_SESSION['sessionvalue'] != $userdeets['sessionvalue'])
{
session_destroy();
Header('Location: logout.php');
}
else
{
$result2 = mysql_query("UPDATE `sessionvalue` WHERE `username`='".$_SESSION['user_id']."' SET `sessionvalue` = RANDOMVALUE''");
$sesval = mysql_fetch_array($result2);
$_SESSION['sessionvalue'] = $seshval
}
Now I know thats not the very code but in essence what you need to do to be secure and have this ability is:
Everytime a page load check a Session value matches a value in the DB.
Every time a page loads set a new session value based on a random generated DB value. you will need to store the username in a session as well.
if the Session ID's do not match then you destroy the session and redirect them.
if it does match you make the new session ID.
if you want to ban a user you can set their sessionvalue in the DB to a value like "BANNED". this value will not allow them to log in either. this way you can control user through a simple web form and you can also generate list of banned users very easily etc etc. I wish I had more time to explain it I hope this helps.
For background, here's my scenario:
I'm building a self-hosted platform for a particular niche, and part of that platform is the login process, which if validated sets a session for the user. On every administration page load, the session is started and the variable $_SESSION['key'] checked to see if it's true.
If it's false, the user is re-directed to the login page with an error telling them to login again.
The problem is this is dependant on a session cookie being set or not set, in the sense that when the session cookie expires and the session is started with session_start() to check $_SESSION['key'], therefore creating a new session cookie with default values (I use session_set_cookie_params() to alter the path, timeout etc) making it impossible to re-login as session cookies do not overwrite from what I can see.
In order to fix this I've thought about using something like session_set_cookie_params(5, ..) before session_start() when checking $_SESSION['key'], which will create a 5 second session cookie, therefore allowing a new one to be created when re-logging in, but I'm not sure whether this would work - and I'm also sure there must be a more efficient way to set/unset a session variable?
Here's my code:
Start session if validated login
if($validated){
session_set_cookie_params(1800, "/inst", $server_name['home']);
session_name("_inst");
session_start();
$_SESSION['key'] = true;
}
Check if $_SESSION['key'] is still true
session_name("_inst");
session_start();
if(!$_SESSION['key']) {
header('Location: ' . $server['home'] . '/login/?error=1');
}
Any answers or advice would be great, and please do ask if you need clarification on anything!
Just issue a session_start() on all pages. This'll unconditionally create a session for you, then you can check for the presence/abscence of the key:
<?php
session_start();
if (!isset($_SESSSION['key'])) { // never logged in, or were logged in and got logged out
... redirect to login ...
exit();
}
if ($_SESSION['key'] != 'expected value') { // logged in, but no longer a valid login.
... redirect to login ...
exit();
}
You shouldn't have to mess with the session cookie settings at all. Leave them at default and simply check for the relevant key(s). if they're not there, then the user is not logged in and should be redirected.
If their session had expired and PHP cleaned up the session file, then they've been effectively logged out, even though they have a it-was-valid-at-one-point-in-time session key, and should get redirected to login again.
I have just started learning PHP, and I wrote an account system with PHP and mySQL for my website. I know the sql stuff is working fine, the problem is my PHP session.
When I go to test it, I can try to login, and it fails. Then, I try to login again, and it will succeed. It always succeeds on the second attempt to login. It never succeeds on the first attempt in Firefox, but it does in Chrome. Also, a couple of times in Chrome, after I succeeded in logging in, going to a some different pages on my site seemed to erase the session. Or, at least, that session was not registering on those other pages. I didn't have that problem on Firefox. I have checked, double-checked, and triple-checked, and all of my pages call session_start() before anything else, so I know that can't be the problem.
I must not have a full enough understanding of PHP sessions, as it's just not working consistently.
After posting this, I tested in IE, and everything works fine there. I log in on the first attempt, and any page I visit maintains my session.
Here is the code for the php script that actually "logs in" the user:
<?php
session_start();
//pass info to mysql(servername, username, password)
$connect = mysql_connect ("localhost", "ggstudio", "mtgertai1");
if (!$connect)
{
die ('Failed to connect: ' . mysql_error());
}
mysql_select_db("ggstudio_accountDatabase", $connect);
//capture data sent to page through login
//usernameField and passwordField
$usernameSubmission = $_POST[usernameField];
$passwordSubmission = $_POST[passwordField];
$validAccount = mysql_query("SELECT * FROM userAccounts WHERE userID = '$usernameSubmission' AND userPassword = '$passwordSubmission'");
$row = mysql_fetch_array($validAccount);
if (($row['userID'] == $usernameSubmission)&&($row['userPassword'] == $passwordSubmission))
{
/*********************************
**********************************
assign global variables to session
after starting session and then***
redirect to user homepage*********
**********************************
**********************************
*/
//get account number from database
$_SESSION['accountNumber']= $row['accountNumber'];
//get first name from database
$_SESSION['firstName']= $row['firstName'];
//get last name from database
$_SESSION['lastName']= $row['lastName'];
//save username into session
$_SESSION['username']= $row['userID'];
//save password into session (only really useful if user wants to change password)
$_SESSION['userPassword']= $row['userPassword'];
//get user's email address from database
$_SESSION['userEmail']= $row['userEmail'];
//get GP from database
$_SESSION['gpoints']= $row['userGloryPoints'];
//get user join date from database
$_SESSION['userJoinDate']= $row['userJoinDate'];
//get user rank
$_SESSION['userRank']= $row['userRank'];
header('Location: http://www.glorygamer.com/account_home.php');
}
else
{
$loginFailed= TRUE;
setcookie("incorrectLogin", $loginFailed, time()+20);
header('Location: http://www.glorygamer.com/shibboleth.php');
}
?>
If the session is working intermittently then I'd say there's one of two things happening:
Your session isn't being set in the browser correctly
Your session isn't being saved on the server in time.
One thing that can happen (especially when you're testing on localhost) is that an authenticated session isn't written to disk in time for the next request, hence the next request appears to be un-authenticated (remember that apache is multi-process; your second request could be handled by another process which isn't aware of what the first is doing). Here's one possible solution:
$_SESSION['userRank']= $row['userRank'];
session_write_close();
header('Location: http://www.glorygamer.com/account_home.php');
The call to session_write_close() should mean that your authenticated session is ready in time for the next request.
HTH.
The first thing I see are the lack of single quotes. Also, you should definitely escape these so that nobody can do any SQL injection on you.
$usernameSubmission = $_POST[usernameField];
$passwordSubmission = $_POST[passwordField];
should be:
$usernameSubmission = mysql_real_escape_string($_POST['usernameField']);
$passwordSubmission = mysql_real_escape_string($_POST['passwordField']);