Jump to content

Recommended Posts

I am trying to learn how to program in PHP. For a long time i was using WAMP and my localhost. When i ran into trouble i searched the web, watched videos and eventually find a solution.

 

Trying to upload my scripts into a shared hosting web server i had some difficulties in basic things, like using $_SESSION superglobal variable.

 

What i want to do is to use a hidden field with a value inside a form, and after submitting the form, to compare the $_SESSION variable to the $_POST variable in order to check for CSRF.

<?php

	//call all custom functions
	require_once('Custom_Functions/functions.php');

	//session must be send before HTML headers

	secure_session_start();

?>
<!DOCTYPE html>
<html lang="en">
<body>
<?php 

	if(isset($_POST['submit']))
	{
		$postvalue = $_POST['input1'];
		$sessionvalue = $_SESSION['hashed_token'];

		echo '<br />==========================<br />';
		echo '<br />AFTER PRESSING SUBMIT<br />';

		echo '<br />==========================<br />';

		echo 'Value of  $_POST["hashed_token"] = '.$postvalue.'<br />';
		echo 'Value of $_SESSION["hashed_token"] = '.$sessionvalue.'<br />';
		

	}


$hashed_token = hash('sha256', uniqid(mt_rand(), TRUE));

$_SESSION['hashed_token'] = $hashed_token;


echo '<br />==========================<br />';
echo '<br />BEFORE PRESSING SUBMIT<br />';

echo '<br />==========================<br />';


echo '<br />Value of $_SESSION["hashed_token"] = '.$hashed_token.'<br />';


?>

<form action="" method="POST">
	<input type="hidden" name="input1" value="<?php echo $hashed_token; ?>" />
	<p><input type="submit" name="submit" /></p>
</form>


</body>


</html>

In this script i have 1 custom function:

 

a) secure_session_start()

function secure_session_start(){

	//Set a custom session name
	$session_name = 'TESTSESSID';

	ini_set('session.use_only_cookies', 1);

	ini_set('session.entropy_file', '/dev/urandom');

	
	if (in_array('sha512', hash_algos())) {
	  
	    ini_set('session.hash_function', 'sha256');
	 }

	ini_set('session.use_trans_sid', 0);

	ini_set('session.hash_bits_per_character', 5);

	ini_set('session.cookie_secure', 1);

	$secure = TRUE;

	$httponly = TRUE;


	$cookieParams = session_get_cookie_params();
	
	session_set_cookie_params($cookieParams['lifetime'], $cookieParams['path'], $cookieParams['domain'], $secure, $httponly);

	session_name($session_name);

	
	ini_set("session.save_path", "/home/SESSIONS");

	session_start();

}

The procedure goes as follows:

 

FIRST COMMUNICATION WITH THE SERVER:

The superglobal variable $_SESSION['hashed_token'] is assigned the random hash value, which is then passed to the hidden input field. I then echo it.

 

RESULT:

 

==========================

BEFORE PRESSING SUBMIT

==========================

Value of $_SESSION["hashed_token"] = 93438a1b9b72085ce9430291acebdc4cfdee9d001b91a26207aebc22e04689fc

 

SECOND COMMUNICATION WITH THE SERVER:

The user press the submit button, the script then checks if the submit button is pressed, and gets in the if statement(because is TRUE). Then i collect the $_POST and $_SESSION values and echo them. New random hash is assigned to the $_SESSION superglobal variable.

 

RESULT:

 

==========================

AFTER PRESSING SUBMIT

==========================
Value of $_POST["hashed_token"] = 93438a1b9b72085ce9430291acebdc4cfdee9d001b91a26207aebc22e04689fc
Value of $_SESSION["hashed_token"] = 8f176aeb3a09a1b30e0ea862c78625d7c11743da933d366cface3fa238388e57

==========================

BEFORE PRESSING SUBMIT

==========================

Value of $_SESSION["hashed_token"] = c3442382b146f03394ad86911018247c57fa19d4a653d0bf6bb9bc7506e88ca0

 

For me this is very weird. The random hash is assigned to the $_SESSION variable, but when i try to call it after the submit is pressed its giving me a complete different value. If i remove the function secure_session_start() and just use session_start() it works:

 

RESULT (using session_start() )

==========================

AFTER PRESSING SUBMIT

==========================
Value of $_POST["hashed_token"] = a5eaaaa38c428af623a599e664ea9c64a2ff0674e18e9250c54e52bbc586b614
Value of $_SESSION["hashed_token"] = a5eaaaa38c428af623a599e664ea9c64a2ff0674e18e9250c54e52bbc586b614

==========================

BEFORE PRESSING SUBMIT

==========================

Value of $_SESSION["hashed_token"] = e2d4acc239a747217860d71a80553abd41142dbeb8f6fafab511caff8a081fc4

 

Any ideas why this is happening? The problem is inside the secure_session_start() function but i cant find out why.

 

Also, when i use the secure_session_start() function and more specifically the ini_set("session.save_path", "/home/SESSIONS"); i am forcing the session to be stored inside the /home/SESSIONS folder. But when i only use the session_start() the session i still gets stored inside that path. I checked my .htaccess and there is nothing storing the sessions in that folder. Why is that?

 

One last thing: When using FIREBUG-->Cookies is see 2 names: the custom one (TESTSESSID) and PHPSESSID(which is the default). Shouldnt i only see the custom session name only?

 

Thanks in advance.

the code you found that's setting the session parameters is setting the session.cookie_secure setting to a true/1 value. this means that the session id cookie will ONLY be sent to the server when making a https request over an encrypted connection.

the code you found that's setting the session parameters is setting the session.cookie_secure setting to a true/1 value. this means that the session id cookie will ONLY be sent to the server when making a https request over an encrypted connection.

Yes i know, but i have an SSL certificate configured to my domain, and i am forcing each page to use https through .htaccess:

 

#TURNS HTTPS ON
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*) https://%{SERVER_NAME}/$1 [R,L]
 
Is this correct?
 
Thanks for the response.

Are you sure that the code in your first post is actually the one you're using? Are you sure that you're generating the anti-CSRF token only in the form script? And does the problem always occur or only sometimes, maybe after you've switched the browser tab?

 

In any case, regenerating the token on every request is a bad idea in the times of tabbed browsing. The problem you currently have is exactly what will happen to your users if they open your forms in multiple tabs: Once they submit a form, the token in the session changes, and the tokens of all other tabs are out of sync and must be manually refreshed. Otherwise the user gets a token mismatch. This is very annoying and has very little benefit for security. In fact, I have a hard time coming up with a scenario where it would even make sense to refresh the token more often than the session ID.

 

Generate the token once when the session is created and keep it until the end of the session. This may in fact fix your problem immediately.

Are you sure that the code in your first post is actually the one you're using? Are you sure that you're generating the anti-CSRF token only in the form script? And does the problem always occur or only sometimes, maybe after you've switched the browser tab?

 

In any case, regenerating the token on every request is a bad idea in the times of tabbed browsing. The problem you currently have is exactly what will happen to your users if they open your forms in multiple tabs: Once they submit a form, the token in the session changes, and the tokens of all other tabs are out of sync and must be manually refreshed. Otherwise the user gets a token mismatch. This is very annoying and has very little benefit for security. In fact, I have a hard time coming up with a scenario where it would even make sense to refresh the token more often than the session ID.

 

Generate the token once when the session is created and keep it until the end of the session. This may in fact fix your problem immediately.

 

Thanks for the advice. Its generally a good approach not to regenerate the token in each reload of the page. I can see that know. To bypass this i added the following code at the top, where the session_start() is:

secure_session_start();

	
$current_sessid =  $_COOKIE['TESTSESSID'];

$new_sessid = session_id();


if($current_sessid != $new_sessid)
{
	$hashed_token = AntiCSRFtoken();
	echo $hashed_token;
	$_SESSION['hashed_token'] = $hashed_token;
}
	

The weird part is that, when i use the custom secure_session_start(), i does not work. When i use the default PHPSESSID it works fine.

session_start();

	
$current_sessid =  $_COOKIE['PHPSESSID'];

$new_sessid = session_id();


if($current_sessid != $new_sessid)
{
	$hashed_token = AntiCSRFtoken();
	echo $hashed_token;
	$_SESSION['hashed_token'] = $hashed_token;
}
	

Any ideas why the custom secure_session_start() causes this kind of trouble? And if cant bypass it and i have to use the session_start() how do i make sure that the following options are enabled for my domain? Is the .htaccess reliable for this purpose? 

ini_set('session.use_only_cookies', 1);

	
ini_set('session.entropy_file', '/dev/urandom');

	
if (in_array('sha512', hash_algos())) {
	   // Set the has function.
	   ini_set('session.hash_function', 'sha256');
}

ini_set('session.use_trans_sid', 0);

	
ini_set('session.hash_bits_per_character', 5);

	
ini_set('session.cookie_secure', 1);

	
$secure = TRUE;

	
$httponly = TRUE;


	

Thanks.

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.