On my server i am starting a new session by calling a static class function.
The problem is that the session id is not being saved in the session cookie, furthermore it seems that no session cookie is being saved at the client (eg. chrome doesn't display a cookie for the website).
Printing out $_COOKIE results in array(0) { }. Same with $_SESSION.
Here is the static class function which starts a new session:
<?php
class Session
{
private function __construct() { }
public static function sec_session_start()
{
$session_name = 'sec_session_id';
$secure = TRUE; // https only
$httponly = true; // javascript can't access session id
$cookieParams = session_get_cookie_params();
session_set_cookie_params($cookieParams['lifetime'],
'/',
'www.example-domain.de',
$secure,
$httponly);
session_name($session_name);
session_start();
session_regenerate_id();
}
}
?>
And at the top of every page i am starting the session with
Session::sec_session_start();
For example when i am at the login page of my website and print out var_dump($_COOKIE) it says array(0) { } instead of array(2) { ["PHPSESSID"]=> string(26) "..." ["sec_session_id"]=> string(26) "..." }.
The php ini looks as follows
php ini
Make sure your website supports https.
session.cookie_secure specifies whether cookies should only be sent
over secure connections.
http://php.net/manual/en/session.configuration.php#ini.session.cookie-secure
If it doesn't, just set the $secure to false.
Hope this will help.
You have have to have session_start as your first line before any session functions.
Related
I am learning php.
I have a class and a function to start a custom session like the following,
Now how can I use the said custom session_start in every php page?
please help.
my code is like
<?php
// myclass.php
class abcd{
function sec_session_start() {
$session_name = 'sec_session_id'; // I have Set a custom session name
$secure = false;
$httponly = true;
if (ini_set('session.use_only_cookies', 1) === FALSE) {
$err='Could not initiate a safe session (ini_set)';
$err = Encryption::encode($err);
header("Location: ../login.php?error_msg=".$err);
exit();
}
// Gets current cookies params.
$cookieParams = session_get_cookie_params();
session_set_cookie_params($cookieParams["lifetime"],
//session_set_cookie_params(time()+3600,
$cookieParams["path"],
$cookieParams["domain"],
$secure,
$httponly);
// Sets the session name to the one set above.
session_name($session_name);
session_start();
session_regenerate_id(true);
}
}
?>
In this case the following error is showing :
Notice: A session had already been started - ignoring session_start()
myphp page is below -
<?php
// mypage.php
include_once "myclass.php";
$mevalue = new abcd;
$mevalue->sec_session_start();
code code code
?>
Please help me to solve this.
A session should last throughout the page visit and not be renewed on each page,
e.g. a user logs in once and this is stored into a session so the user doesn't need to login again for each new page or click.
Mostly a session starts if someone visits your page and remains until the user leaves the page -> closing the session.
The best way is to check if a session is open for this user and only start a session if the user doesn't have one.
To close a session one can use
session_write_close ( void ) : bool
Source
With this you can update your code to have a get_session function. In this function you can check if a session exists and use that one, if not start a new one
class abcd{
function init_session()
{
if (!isset($_SESSION)) {
$this->sec_session_start();
}
}
function sec_session_start() {....
And in your page
$mevalue->init_session();
I have this login mechanism with an additional authentication barrier presented before the user can change sensitive information (such as their password, email, etc.) through their profile.
There is a pre-session on the login page that I use for verifying the CSRF token, and I have code responsible for regenerating the session ID before the current session is given the user data and authentication status.
For the login process, everything goes fine. The session ID before and after logging in are different. No problems here.
The problem begins when I go to authentication.php, which serves as a barrier presented to the user before they can change their password. Upon successfully validating the provided password against the hash from the database, I would set a new session variable named "authenticated" that gives access to the next page, pass-change.php.
Before "authenticated" is set, the session ID must be, again, regenerated.
That's where my problem lies.
Instead of taking me to pass-change.php with a brand new session ID, it destroys the session; consequently, I am taken back to login.php, presumably because $_SESSION['loggedin'] is no longer set.
// This is my session_start() function
function my_session_start() {
session_start();
if (isset($_SESSION['destroyed'])) {
// checks if session has been 'destroyed' for more than 5 minutes
if ($_SESSION['destroyed'] < time() - 300) {
// if true, wipe all session variables and throw exception
$_SESSION = array();
throw new Exception('This session is obsolete');
}
if (isset($_SESSION['new_session_id'])) {
// if new_session_id is still set, close the session and attempt to start a new session with it
session_commit();
session_id($_SESSION['new_session_id']);
session_start();
return;
}
}
}
my_session_start();
// This is my session_regenerate_id() function
function my_session_regenerate_id() {
// new session ID is created and stored for later use
$new_session_id = session_create_id();
$_SESSION['new_session_id'] = $new_session_id;
// set the current session as 'destroyed' and save current time
$_SESSION['destroyed'] = time();
// close session
session_commit();
// set the new ID we created previously and start a new session
session_id($new_session_id);
ini_set('session.use_strict_mode', '0');
session_start();
ini_set('session.use_strict_mode', '1');
// unset these variables as they should not be with the new session
unset($_SESSION['destroyed']);
unset($_SESSION['new_session_id']);
}
// Sessions are always started at the beginning of every file. my_session_regenerate_id() is called right before I define session variables containing authentication flags or user data. This is done at login.php after password is checked against the hash and deemed correct; and also called at authentication.php after the user provides their correct password.
// this is the part where I call my_session_regenerate_id() at authentication.php
if (password_verify($pass, $hash)) {
my_session_regenerate_id();
$_SESSION["authenticated"] = time();
header('Location: pass-change.php');
}
// some pages redirect when you're not logged in
if (!isset($_SESSION["loggedin"])) {
header('Location: login.php');
I expect the session to retain its status after my_session_regenerate_id() is called at authentication.php, but it gets destroyed. All it should be doing is: set current session as 'destroyed', create new session ID and change to it, while retaining all other user data and authentication flags such as $_SESSION['loggedin'].
EDIT
As requested, here are the results from printing all session variable data:
Before login, at login.php:
array(2) {
["usertoken"]=>
string(64) "519f82f974fb8e79b30ee950be9ba63048278105bd8e983fa832e754aaf47b3c"
["usrtokentime"]=>
int(1553865620)
}
After first run of session ID regeneration, at profile.php:
Session ID changed after login
array(7) {
["lastLogin"]=>
int(1553864997)
["loggedin"]=>
string(0) ""
["registerDate"]=>
int(1553605077)
["name"]=>
string(14) "User Name"
["email"]=>
string(26) "user.email#gmail.com"
["type"]=>
string(1) "A"
["usertoken"]=>
string(0) ""
}
Second run of session ID regeneration. After submitting the form at authentication.php and being thrown back to login.php:
Session ID changed again
array(3) {
["authenticated"]=>
int(1553865804)
["usertoken"]=>
string(64) "ba454364870f5d8cdfd4e5a3213d3a34117f161c098c97060e70327d3a983501"
["usrtokentime"]=>
int(1553865804)
}
So, only "authenticated" session variable survived. All others were wiped out.
Thanks to 04FS, I was able to pinpoint the problem.
The my_session_regenerate_id() function is wiping all the session variables when it is called. The solution is to set all the variables after the function call, and that was easy to do in my code, because a prepared statement object was already available at that point to pull in all the data.
This is how my function call code looks like now at authentication.php:
if (password_verify($pass, $hash)) {
my_session_regenerate_id();
$_SESSION["authenticated"] = time();
$_SESSION["lastLogin"] = $res['lastLogin'];
$_SESSION["loggedin"] = "";
$_SESSION["registerDate"] = $res['registerDate'];
$_SESSION["name"] = $res['name'];
$_SESSION["email"] = $res['email'];
$_SESSION["type"] = $res['type'];
$_SESSION["usertoken"] = "";
header('Location: pass-change.php');
}
In order to increase the security for the logged-in users, after the session_start(); and assigning the other session variables, I also try to store the HTTP_USER_AGENT value, using $_SESSION['agent'] = md5($_SERVER['HTTP_USER_AGENT']); for the login.php page.
Besides, in the login.php page, I redirect logged-in users to the home page if they try to visit it again without logging it out first, using the conditional like this:
if (isset($_SESSION['agent']) OR ($_SESSION['agent'] = md5($_SERVER['HTTP_USER_AGENT']) ) ) {
//redirect to home page
header('location:http://index.php.com');
exit();
}
The question is that in my logout.php page I code the conditional like this:
if (!isset($_SESSION['agent']) OR ($_SESSION['agent'] != md5($_SERVER['HTTP_USER_AGENT']) ) ) {
//Redirect to home page
}else{
$_SESSION = array(); // Destroy the variables.
session_destroy(); // Destroy the session itself.
setcookie (session_name(), '', time()-3600); // Destroy the cookie.
}
Then I came back to visit the login.php page again as a logged-in user (session has been set), it still redirected me to the home page.
Then I tried deleting the cookies in the FF browser, close it, then revisited the login.php page, it still redirected me.
Do you know what I was wrong or missing?
NOTE: I have no problem to destroy the session if not storing **the HTTP_USER_AGENT
You have an assignment where you want to check.
Change:
if (isset($_SESSION['agent']) OR ($_SESSION['agent'] = md5($_SERVER['HTTP_USER_AGENT']) ) ) {
to
if (isset($_SESSION['agent']) OR ($_SESSION['agent'] == md5($_SERVER['HTTP_USER_AGENT']) ) ) {
off topic security tip(maybe helpfull):
public function Start_Secure_Session()
{
// Forces sessions to only use cookies.
ini_set('session.use_only_cookies', 1);
// Gets current cookies params
$cookieParams = session_get_cookie_params();
// Set Cookie Params
session_set_cookie_params($cookieParams["lifetime"], $cookieParams["path"], $cookieParams["domain"], $this->isHTTPS, $this- >deny_java_session_id);
// Sets the session name
session_name($this->session_name);
// Start the php session
session_start();
// If new session or expired, generate new id
if (!isset($_SESSION['new_session']))
{
$_SESSION['new_session'] = "true";
// regenerate the session, delete the old one.
session_regenerate_id(true);
}
}
I'm trying to create a secure session by creating start_secure_session() function like this:
function start_secure_session() {
$session_name = 'secure_session';
$secure = true;
$httponly = true;
if (ini_set('session.use_only_cookies', 1) === false) {
die('error');
}
$cookie_params = session_get_cookie_params();
session_set_cookie_params($cookie_params["lifetime"],
$cookie_params["path"],
$cookie_params["domain"],
$secure,
$httponly);
session_name($session_name);
session_start();
session_regenerate_id(true);
}
The problem is, start_secure_session() is not saving $_SESSION super global variable. It's unset immediately when the page refreshed. It works only if I comment this out:
//$cookie_params = session_get_cookie_params();
//session_set_cookie_params($cookie_params["lifetime"],
// $cookie_params["path"],
// $cookie_params["domain"],
// $secure,
// $httponly);
or in other words, not setting a custom cookie params.
What should I do to make it works? So, the session_start() can work properly and $_SESSION variable can remember it's value?
I think it is because of the secure=TRUE and you not using HTTPS?
It will not create a session on a non-secure connection with secure set to TRUE.
I've just begun using sessions and am having some headaches, I had this working last night, now opening it today...no longer works.
In my login processor I have the following if everything is OK. This script works fine, I have echoed the session variables to ensure that the array works, and it does.
$username - > post from login script
$encrypt_password -> created from password check further up the script
{
$session_name = 'LOGIN'; // Set a custom session name
$secure = false; // Set to true if using https.
$httponly = true; // This stops javascript being able to access the session id.
$cookie_lifetime = '3600';
$cookie_path = '/';
$cookie_domain = '127.0.0.1';
session_set_cookie_params($cookie_lifetime, $cookie_path, $cookie_domain, $secure, $httponly);
session_name($session_name); // Sets the session name to the one set above.
$group = $row['group_type'];
$user_browser = $_SERVER['HTTP_USER_AGENT']; /*grabs browser info*/
$user_id = preg_replace("/[^a-zA-Z0-9_\-]+/", "", $username); /*XSS Protection*/
$group_id = preg_replace("/[^a-zA-Z0-9_\-]+/", "", $group); /*XSS Protection*/
session_start();
$_SESSION['user']=$user_id;
$_SESSION['group_name']=$group_id;
$_SESSION['login_string'] = hash('sha512', $user_browser.$encrypt_password);
session_write_close();
header("location:".$group_id."_index.php");
}
I have created an include file which gathers the info from the session, included on every protected page, this is where it fell apart. I have created custom error codes for each if statement and have found that the if statement here fails. Echoing the session variables or evening printing the session array returns nothing.
$session_name = 'LOGIN'; // Set a custom session name
$secure = false; // Set to true if using https.
$httponly = true; // This stops javascript being able to access the session id.
$cookie_lifetime = '3600';
$cookie_path = '/';
$cookie_domain = '127.0.0.1';
session_set_cookie_params($cookie_lifetime, $cookie_path, $cookie_domain, $secure, $httponly);
session_name($session_name); // Sets the session name to the one set above.
session_start(); // Start the php session
session_regenerate_id(false); // regenerated the session, delete the old one.
if(isset($_SESSION['user'],$_SESSION['group_name'], $_SESSION['login_string']))
I was changing around the way the user groups worked before this broke, however none of the variables make it through. I am learning from his tut by the way: create a secure login script in php and mysql
Also do I need to call the session parameters every time a user visits a protected page?
Thanks in advance for any pointers.
Try putting session_start(); on TOP of everything, most importantly before you're calling a session. You're calling session_name($session_name); before it even started.
it=session
your regenerating the session on every page, which causes the previous session to destroy data.
remove session_regenerate_id(false);