Jump to content

Secure cookies on login form


sanjsimi

Recommended Posts

Hi, i creating a login form with cookies and i want to know if my code is secure, do i need extra protection for cookies ?

 

I want to know because i will store that hash in database and check if it same when user come back and make new hash then store new in database.

 

This is my script:

 

Login.php

<?php

include "../config.php";

if (isset($_COOKIE['hash']) && isset($_POST['uid']) && isset($_COOKIE['uname'])) {
	die("You are already logged in.");
}

if (isset($_POST['submit'])) {
	$username = htmlentities(strip_tags($_POST['username']));
	$password = htmlentities(strip_tags($_POST['password']));

	if ($username == '' || $password == '') {
		$error = 'Please enter username and password.';
	} else {
		$data = $users->user_login($username, $password);
		if ($username == $data['username'] && password_verify($password, $data['password'])) {

			//$error = 'login user';
			$hash = sha1(mt_rand(6000, 9000));

			setcookie('hash', $hash, time()+60*60*24*365);
			setcookie('uid', $data['user_id'], time()+60*60*24*365);
			setcookie('uname', $data['username'], time()+60*60*24*365);

			header("Location: login-success.php");
			exit();
		} else {
			$error = 'Invalid username or password.';
		}
	}

	
}


?>
<form action="" method="post" class="login-form">
	<label for="username">Username</label>
	<input type="text" name="username" id="username">
	<label for="password">Password</label>
	<input type="password" name="password" id="password">
	<input type="submit" name="submit" value="Login">
</form>

Logout.php

<?php

if (isset($_COOKIE['hash']) && isset($_COOKIE['uid']) && isset($_COOKIE['uname'])) {
	unset($_COOKIE['hash']);
	unset($_COOKIE['uid']);
	unset($_COOKIE['uid']);
	setcookie('hash', null, -1);
	setcookie('uid', null, -1);
	setcookie('uname', null, -1);
	header("Location: index.php");
	exit();
}

?>

User class

class Users
{
	protected $db;
	
	function __construct(PDO $db)
	{
		$this->db = $db;
	}
	/*
	*	login user
	*
	*
	*/
	public function user_login($username, $password)
	{
		$query = $this->db->prepare("SELECT user_id, username, password FROM users WHERE username = :username");
		$query->execute(array(':username' => $username));

		if ($query->rowCount() > 0) {
			return $query->fetch();
		}
	}
Link to comment
Share on other sites

I'll ask you one question:

 

If I were to tell you that I could magically change the cookies on my computer to use any values I wanted, how would that affect your application?

 

Because

 

I can totally change the cookies on my computer to use any values I wanted. Anyone can do that.

 

Link to comment
Share on other sites

I see a lot of people texting and driving... doesn't make it safe.

Cookies are a very insecure way of managing user access. At most, I would store the user's username in a cookie so all they need to do is enter their password. If you're adamant about keeping someone logged in using cookies, I would read this:

 

https://paragonie.com/blog/2015/04/secure-authentication-php-with-long-term-persistence

Link to comment
Share on other sites

They use cookies for a very specific purpose. Either they store the session ID which points to a server-side session (a PHP standard feature), or they store the actual user data but protect its authenticity with a message authentication code (which is more exotic and complex).

 

In any case, I strongly recommend you don't invent your own mechanism. This usually doesn't end well. Use the standard sessions in PHP.

Link to comment
Share on other sites

Um, what? This is how the WWW works. Cookies are in fact much more secure than many of the alternatives (like HTTP Basic authentication or tokens in the URL).

I'm sure DulongC meant that storing the data in cookies is insecure, not the literal act of using cookies at all. We all know cookies are important and a fundamental aspect of how the internet works... well, except for the EU.
Link to comment
Share on other sites

Yes, cookies are important and they can be very useful when used properly. However my understanding of:

 

I want to know because i will store that hash in database and check if it same when user come back

Means that he wants to go beyond a standard session and keep his user's logged in every time they visit the site using a cookie. When this is done, it creates a potential security hole as I can now take steal your cookie, put it on my computer, and the website will think I am you and allow me full access to your account. There are ways of managing this in a semi-secure way, but it needs to be done properly, which is explained in detail in the blog I linked to for the OP should they wish to go this route.

 

If I misunderstood and the OP just wants to create a single session, not a persistent one, then he can ignore what I said.

Link to comment
Share on other sites

I'm still not sure if we're on the same page here.

 

Yes, the OP wants to keep the user logged in, and, yes, he/she wants to use cookies for that. This is exactly what sessions do. It has nothing to do with “going beyond standard sessions”. In fact, even storing the user data directly in a cookie is valid and common practice, if the integrity of that data is cryptographically protected and the server rejects all manipulated sessions. Big applications sometimes use this to take the burden of session management away from the servers. I wouldn't recommend it to less experienced programmers, but it's one way of implementing sessions.

 

You keep making this distinction between “standard sessions” and “persistent sessions”, but the only difference is that “persistent sessions” are supposed to run longer -- whatever that means. Technically, there are just sessions, and you may very well turn standard PHP sessions into “persistent” ones simply by increasing the time limit. Since the OP never even mentioned time, the whole persistence thing seems to be irrelevant.

 

Yes, session cookies can be transferred from one machine to another, which is why the cookie needs to be protected through HTTPS and attributes like Secure and HttpOnly. But again, this is all standard stuff, nothing special. Some people try to bind the session to a particular IP address or user agent, but this is unrealiable (IP addresses are typically shared and reused) and can create lots of problems for legitimate users who simply cannot or don't want to keep the same IP address for a long time.

 

Long story short: Cookie-based sessions are the standard solution, and there's nothing wrong with that as long as you use correct a implementation. I'll happily discuss security improvements, but right now, I'm more concerned about the basics.

 

Of course we all agree that the original implementation of the OP is unacceptable. But this is the programmer's fault, not a problem of cookies.

Link to comment
Share on other sites

@Jacques1 can you please explain me more about secure session or cookies and how to proper use them.

 

I was always made login systems with session's and i wanted now to change it to cookies but its as i see now complicated same as a session.

 

If i don't protect session i see on many pages and forums that session can be hijacked easy on http protocol or with javascript.

 

I was storing only session random key and user id in 1 database table and when user come back on page i was checking query->user id->session random number if they exists and match with user session when he is on page.

Link to comment
Share on other sites

Making PHP sessions secure

 

If you have PHP 7 (which you should), a few parameters are different from what I wrote in 2013, but the basics are the same.

 

Note that session security must also include protection against XSS and CSRF attacks. Otherwise an attacker can just make requests on behalf of another user without having to actually “steal” the session. So make sure you have proper HTML escaping and anti-CSRF tokens in place.

Link to comment
Share on other sites

Thanks for the links and for explanation. I'm using PHP 7.1.1 at the moment on my localhost.

 

Oh as i see those 3 settings are removed in PHP 7.0

session.entropy_file		/dev/urandom
session.entropy_length		16
session.hash_function		sha256
Link to comment
Share on other sites

The short answer to the OP's question is, "No, your cookies are not secure because you're only passing the first three parameters to the setcookie function. The other parameters are really important and should not be ignored"…

 

 

bool setcookie ( string $name [, string $value = "" [, int $expire = 0 [, string $path = "" [, string $domain = "" [, bool $secure = false [, bool $httponly = false ]]]]]] )

 

$path – You'll probably want to set to '/' since you probably need your cookie available on all pages on your site.

 

$domain – I'm not sure if you're using a subdomain, but set it to the most restrictive value possible (for maximum security). So 'www.yourdomain.com'. If you're not using a subdomain I've noticed the browsers implement things differently than the W3 spec. The spec says that '.yourdomain.com' and 'yourdomain.com' should act the same way (e.g. the cookie is available on all subdomains), but if your host name is yourdomain.com (e.g. no subdomain), then setting $domain to 'yourdomain.com' only sends it to that one host name. It's not available on other subdomains. To get all subdomans you'll need to set $domain to '.yourdomain.com'.

 

$secure – should be set to true (or 1). That means the cookie will only be sent over encrypted, HTTPS connections. Which means your site needs to be encrypted. If it's not, stop now and get it encrypted and then revisit your cookie question.

 

$httponly – should be set to true (or 1). That will stop it from being available to Javascript in standards compliant browsers.

 

There are other things you can do to increase security (many of which are mentioned above), but you first need to start with using all the parameters in the setcookie command.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • 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.