Page 3 of 4

Posted: Thu Sep 22, 2005 8:01 am
by Jenk
Roja wrote:
Jenk wrote:It's not ott at all.
Sorry, I disagree. It is over the top, and can be harmful.
Jenk wrote:Regenerating the session ID on each page is good practice.
Regenerating the session ID on every page load can cause significant problems with back button behavior in web apps. Ilia posted about it, and its appeared on multiple mailing lists.

The current best practice is to regen the id on authentication or priveledge change, as you can see at Chris Shifflet's blog:
http://shiflett.org/articles/security-corner-feb2004
call session_regenerate_id() whenever a user successfully logs in, since this is the moment the session data becomes sensitive for most applications
(Many other sites echo that suggestion).

To use your analogy, instead of changing the locks everytime you unlock the door, you suggest changing the locks everytime someone USES the door - lock or not. Since doing so can break back button behavior in many cases, its harmful AND it gains you little extra security.

Overall, I'd say that fits the description of over the top.
And the sarcastic wit was necessary, because?

Courses for horses.. I've seen sites such as online casino's NEED the session id regenerated on every page, where going "back" is actually a bad thing anyway, and given they are dealing with financials, every possible opportunity must be taken to prevent any form of infiltration.

Posted: Thu Sep 22, 2005 8:44 am
by Roja
Jenk wrote:And the sarcastic wit was necessary, because?
You'll find many of the inhabitants of these forums have lots of sarcasm.

Sadly, the w3c still hasn't added a <sarcasm> tag to the html standard, mostly because there is such a wide disagreement on where it is appropriate, and what the definition of sarcasm is. ;)
Jenk wrote:Courses for horses.. I've seen sites such as online casino's NEED the session id regenerated on every page, where going "back" is actually a bad thing anyway, and given they are dealing with financials, every possible opportunity must be taken to prevent any form of infiltration.
I would argue that "need" is the wrong term there, in that the gain isn't significant enough to offset the loss of functionality. Arguing that "back" is a bad thing is definitely specific to the implementation, and as a general statement, its not a bad thing. Its a user interface standard for a reason.

Regardless, I will agree that if you want to be absolutely paranoid, you can regenerate the id on absolutely every page, and it will gain you some trivial amount of additional security.

Posted: Thu Sep 22, 2005 9:37 am
by patrikG
Jenk wrote:And the sarcastic wit was necessary, because?
Sarcasm? What sarcasm?

Posted: Thu Sep 22, 2005 9:59 am
by Maugrim_The_Reaper
One man's wit, is another man's sarcasm...

Posted: Thu Sep 22, 2005 10:26 am
by John Cartwright
Back on topic mateys.

Posted: Thu Sep 22, 2005 10:35 am
by Maugrim_The_Reaper
Seems to an infectious case of "Piratism A" travelling the forums...;)

BACK on topic...seems pointless (or I should say of minimal added value) to do so for every page. Maybe if your app uses a few tricks to prevent back usage they can do so - even then seems a little limiting.

Re: Sessions and security

Posted: Wed Sep 28, 2005 12:25 am
by ahmedd
session_start();

Posted: Wed Sep 28, 2005 1:01 am
by Ree
session_destroy();

Anything else you wanted to know? :D

Quite a post above... doesn't tell you anything, but you can't say it's completely off-topic either... :D

Posted: Wed Sep 28, 2005 9:39 am
by Maugrim_The_Reaper
I would have found a mention of session_regenerate_id() more on topic... Maybe followed about a rant on why you should destroy the previous session beforehand... One of those fire and brimstone rants...;)

'Twas a newbie y' see...

Posted: Wed Sep 28, 2005 3:35 pm
by mat106
Sorry in advance for the pedanticness of this post... Just trying to understand how onetime hashing should be done
Roja wrote: 4. One-time pad/hashing - When a user goes to login, send him a one-time random number. Thats called a one-time pad. Hash that pad AND the hash of their password and send THAT. The server can do the same thing, and then that same token can't be reused later (because its only used once - one-time).
"When a user goes to login,send him a one-time random number"
Should the random number be hashed before it's sent to the user or doesn't that add anything to the security? Is that what you mean when you say Hash that pad? Also what's the best way for the user to receive the random number (or hashed random number). Should it be a hidden form field, a cookie, a session variable, something else?

...AND the hash of their password and send THAT
So hash the hash of the password?

The server can do the same thing
Should the server depend on the user sending the hashed random number back to it or should the server store the random number (or its hash) in a database at the same time as the random number is sent to the user in the first place?

Thanks

Posted: Wed Sep 28, 2005 4:42 pm
by Maugrim_The_Reaper
Whether you hash the random number itself or not isn't all that important - I tend to, probably force of habit more than anything else though.

The random salt would be passed through a hidden form field, and concatenated to the password. The full string salt+hashedpassword would be hashed. Should note the password must be hashed before being added to the salt - we are assuming passwords are not stored as plain text on the database. The server would store the salt temporarily on the database so it could generate the response it expects back from the client. All you need then is a little javascript client-side to perform the hashing and empty the password field (adding the new hash to a reponse field or similar). To be compatible with all users - ensure that if the login test fails you allow a similar check for a plain text password, i.e. not all clients will have javascript enabled ;).

Look out for a tutorial on such a system in the near future...

Posted: Wed Sep 28, 2005 7:25 pm
by Roja
mat106 wrote:"When a user goes to login,send him a one-time random number"
Should the random number be hashed before it's sent to the user or doesn't that add anything to the security?
It really doesn't add anything to the security - *as long as it is a one-time only pad/salt*.
mat106 wrote:Is that what you mean when you say Hash that pad?
I was really unclear there, so let me explain a bit.

First, you need to send the pad/salt (a one-time random code) to the user. That code needs to be verified by the server. Thankfully, the server can hash the pad, so we can have the user send back a hash instead. So, in javascript, we can hash the one-time-pad (OTP) and send that (instead of the pad in cleartext).

Second, you need to give the server the hash of the user's password. We don't want to send the cleartext password, obviously.

Third, you need to ensure that neither have been tampered with, so you do: $bigthing = hash(hash(OTP) + hash(password)).

That way, you get confidentiality (we don't send anything back in cleartext), and integrity (we can repeat the process on the server side to verify it hasn't been tampered with).
mat106 wrote:Also what's the best way for the user to receive the random number (or hashed random number). Should it be a hidden form field, a cookie, a session variable, something else?
If they just got to the login page (presumably the first page), they don't have a session to transport variables on. Also, the session variables are server-side, not client-side, so that doesn't help.

Cookies and form fields are essentially equal in terms of the stream, but on the client side, I'd favor forms. The reasons are really far too indepth to go into here. :)
mat106 wrote:Should the server depend on the user sending the hashed random number back to it or should the server store the random number (or its hash) in a database at the same time as the random number is sent to the user in the first place?
When the server sends the OTP to the user (NOT HASHED!), it should store it. Why? To ensure it does not get reused, or used by the wrong user (an attacker).

Once the user logs in, you can either remove it (and start over again), or store it for some predefined period of time before deleting it, to ensure that numbers don't get reused.

Technically, the latter is the more secure, but it gets really unwieldy, unrealistic, and frankly, you'd get a bigger win by making sure the OTP's had better randomness.

All of the above is simply my opinions on how secure logins should be done. :)

Posted: Thu Sep 29, 2005 6:04 am
by mat106
Ok... first thanks to Maugrim_The_Reaper and Roja for their clear replies. Now... the script that just doesn't seem to work the way it's supposed to! (surprise, surprise)

The problems i am having are that the script seems to have a mind of its own as to what value of the variable $OTP it inserts in the database. Sometimes it inserts the same value as the value of document.nfc_login_form.hidden.value and sometimes it doesn't. As far as i can see it does this on a completely random case (although obviously that must not be the case). When it "decides" to insert the wrong value the value it inserts is ALWAYS 2147483647 !!!.

The othe problem is that when it does actually insert the correct value of $OTP into the database table and i try to log in (with the correct password) i get a wrong username/password message. I suspect that might something to do with this line:

Code: Select all

$final_server_hash = md5(md5("$row[OTP]") + md5("5f08df9d7feaa0e0c453280699bacb05"));
N.B. I'm not using a database of users with a unique password for each user. The password (and username) are the same for all users. 5f08df9d7feaa0e0c453280699bacb05 is the md5 hash of the password. I know it's not good practice to have the same username and password for everyone but it is appropriate for the project at hand.

Code: Select all

<?php
ob_start("ob_gzhandler");
?>
<?php
//starts session so as to be able to use session variables
session_start();
//checks whether the form fields for username and password have been filled in. 
if (isset($_POST["user"]) && isset($_POST["pass"]) && isset($_POST["hidden"]))
	{
	$final_client_hash = $_POST["hidden"];
	
	//calculate the final hash, i.e. md5(md5(OTP)+md5(password))  on the server in order to compare with that sent from the client
	require_once("../includes/db_connect.php");
	$get_OTP = mysql_query("SELECT * FROM OTP");
	while($row = mysql_fetch_array($get_OTP, MYSQL_BOTH))
		{
		$final_server_hash = md5(md5("$row[OTP]") + md5("5f08df9d7feaa0e0c453280699bacb05"));
		if ($final_server_hash == $final_client_hash)
			{
			$delete = mysql_query("DELETE FROM OTP WHERE OTP = '$row[OTP]'");
			session_register("authorised");
			$HTTP_SESSION_VARS["authorised"] = true;
			unset($_POST["user"]);
			unset($_POST["pass"]);
			header ("Location: view.php");
			}
			else
			{
			$errormessage = "Wrong username and/or password! Please try again.";
			}
		}
		unset($_POST["user"]);
		unset($_POST["pass"]);
	}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-type" content="application/xhtml+xml; charset=iso-8859-1" />
<title>Title</title>
<link rel="stylesheet" type="text/css" media="screen" href="filename1.css" />
<link rel="stylesheet" type="text/css" media="screen" href="filename2.css" />
</head>
<body onload="document.nfc_login_form.user.focus();">
<div id="blackbar"><img src="../path/image.gif" alt="" /></div>
<div id="skeleton">
<div id="navigation"><?php require_once("../some_directory/filename.php") ?></div>
<!-- <div id="branding"></div> -->

<!-- Content starts -->

<div id="content">

<!-- Left content starts -->

<div id="maincontent">
<?php
if (isset($HTTP_SESSION_VARS["authorised"]) && $HTTP_SESSION_VARS["authorised"] == true)
	{ 
	echo "<h3>Login Status</h3>";
	echo "<br />";
	echo "<p>Brief status message and options to logout</p>";
	}
	else
	{
?>
<h3>Login</h3>
<br />
<p>Please type your username and password in order to login.</p>
<?php 
//display error message if $errormessage is set and not null
if (isset($errormessage) && $errormessage != '') echo ("<p class='error'>$errormessage</p>");

//generate OTP (One Time Pad)
$random_number1 = mt_rand();
$random_number2 = mt_rand();
$OTP = $random_number1+$random_number2;

// store OTP in OTP table of database
require_once("../some_directory/db_connect.php");
$insert_OTP = MYSQL_QUERY("INSERT INTO OTP (OTP) VALUES ('$OTP')") or die(mysql_error());
?>

<div id="signin">
<!-- script required for client-side md5 hash -->
<script src="md5.js" type="text/javascript"></script>

<form  onsubmit="javascript:document.nfc_login_form.hidden.value=hex_md5(hex_md5(document.nfc_login_form.hidden.value) + hex_md5(document.nfc_login_form.pass.value))" method="post" name="nfc_login_form" id="nfc_login_form">
<fieldset>
<label for="user">Username:</label><br />
<input class="input" name="user" id="user" type="text" /><br />
<label for="pass">Password:</label><br />
<input class="input" name="pass" id="pass" type="password" /><br />
<input type="submit" name="btnLogin" value="Login" />
</fieldset>
<input name="hidden" id="hidden" value="<?php echo $OTP ?>" />
</form>
</div>
<?php
$OTP = null;
	}
?>
</div>

<!-- left content ends -->

</div>

<!-- content ends and footer begins -->

<br /><br /><div id="footer"><img src="filename.gif" alt="" /></div>

<!-- footer ends -->

</div>
</body>
</html>
Can anyone see what the problem(s) is/are ???

Thanks.

Posted: Thu Sep 29, 2005 6:42 am
by mickd
after you insert the OTP into the database, if another person visits the login page and it inserts another value into the table before the other user logs in and removes theirs, how does the script know which OTP to use for which user serverside?

Posted: Thu Sep 29, 2005 6:58 am
by mat106
It doesn't need to know which OTP to use since it runs through all values of OTP using

Code: Select all

while($row = mysql_fetch_array($get_OTP, MYSQL_BOTH))
Any ideas anyone as to the problem i mentioned. As i said, for some bizarre reason it always seems to insert the value 2147483647 intot the database. If i echo the value of $OTP by placing echo $OTP; immediately after

Code: Select all

$OTP = $random_number1+$random_number2;
i get a random number but when i use:

Code: Select all

$insert_OTP = MYSQL_QUERY("INSERT INTO OTP (OTP) VALUES ('$OTP')") or die(mysql_error());
to insert the value into the database, 2147483647 !!