Securing a Login

Ok, I’ve scoured countless php websites. I’ve read plenty of advice about how NOT to do things, but very little about how to correctly deal with secure logins.

First of all, I access the database to compare username and password to make sure the user is allowed access. I’ve read that it is recommended that the connection script be an included file and reside in a folder outside the root directory that cannot be accessed via a web browser. That’s all well and good of course, but the host I am using (I cannot change this, management just doesn’t understand!) does not allow me to create folders outside root. So how do I otherwise protect the password of the database? Since my database only includes user information, and the passwords stored within the database are encrypted, need I worry about keeping the database password any more secure than it already is? I would imagine I do!

This brings me to my second question… The user types in his username and password. The users password is stored in the database. However it’s encrypted. How can I compare the encrypted password from the database to the unencrypted password the user provides. The basic solution is to encrypt the user-entered password, but how do I know how to encrypt it? I’ve seen several encryption techniques. How do I know which one to use?

My third question is once I’ve confirmed the user is allowed to enter the website, how do I make each successive page aware that this user is actually allowed to access each page. It doesn’t make sense to have them enter their username and password each page (although I’m sure this is the most secure method!). I know how to pass data from one page to the next using the GET and POST method, but that hardly seems the best way to do this. I’ve read a little about using sessions, but I haven’t come across anything that explicitly explains how to use them for confirming the user attempting access is the one that I previously confirmed. I’ve also read that sessions are easy to hack once you know the session id which I have to pass using the GET method, which makes them seem useless for this application. I imagine I’m missing something. It would be easy for there to be something like a PASS method so I could use something like $username = $_PASS[‘username’]; but I don’t think that exists (it should!).

I’m sorry for the long winded explanations, but I’m only barely better than a complete novice at php, and I’ve never had to be concerned with security before. Furthermore, please do no think that I want you to write all the code for me, but rather explain the process, or at least point me in the right direction. It seems to me that the only ways to pass data between pages, exposes the data to potentially malicious users, or requires too much inconvenience for the authorized users.

Thanks in advance for any help or direction you can provide!
Lee

First of all: realize that security and userfriendliness are two sides of a scale: if one goes up, the other comes down. To find the balance between those two, a third factor comes into play: how secure do you want it to really be? If this script is going to be exposed to the outside world, and will deal with sensitive data, you’ll want to set your priorities differently than when you have a simple intranet newspage. These are things to consider.

It’s okay to store the file with the database credentials in the webfolder. Just make sure it’s processed by the PHP engine, and not binary or text (so giving it the .php extension would be fine). If people find out this file exists, you’ll want to show them an error, or a white page, but not its contents, when they try to open it. Of course, saving this file outside the webroot is safer, but it’s not a big deal if that’s not possible. Just keep in mind what can and cannot be done with it.

What I do with user passwords, is make a hash (one-way encryption) of it in the PHP script, then store it in a VARCHAR/CHAR/TEXT in the database. My hashing algorythm of choice is md5(), but any hashing algorythm will do. Read up on the different hashing functions PHP offers on the php.net manual. After the user has provided their password, you can simply hash the password, and compare the hashes. MD5 has a collision rate of one in 5 billion or so, so you don’t have to worry about wrong passwords being accepted.

As for your $_PASS suggestion, a construction like that already exists ;) It’s called $_SESSION. You’re going to have to read up on the mechanism in the manual though, as I’m not too familiar with it (I use $_COOKIE myself, though I suspect $_SESSION to be more secure and versatile).

Ahh! See I read about sessions but I couldn’t see exactly what the benefits were. I’ll read up more on that!

And thanks for explaining how to use md5. That was something else I wasn’t clear on.

Thanks for that info.

One question… Is it possible for someone to “download” the .php documents directly using a web browser?

Anyone else have any suggestions on security improvement?

PHP files can only be downloaded if you don’t have the PHP engine process them (in other words: if your phpinfo() page shows up instead of giving a popup ‘What would you like to do with this file’, you’re safe). You can test this yourself by trying to download the page from your server.

I wanted to jump in on this conversation and ask exactly how one would secure there .php files as you mentioned earlier ‘if people find out this file exists, you’ll want to show them an error, or a white page, but not its contents, when they try to open it.’
Thanks for your help.

If you have a page:

<?php
$myUsername = "username";
$myPassword  = "password";
?>

And you request this page directly from the browser, it would display a white page.
It’s possible to test for a variable being initialized so the page gives an error when not requested through another page:

<?php
if ($myVariable != "Called This Page From Another Page") {
  die("My Error Message");
}

$myUsername = "username";
$myPassword = "password";
?>

You’ll have to keep in mind that wherever you want to include these credentials, you’ll have to first set a variable $myVariable with the value “Called This Page From Another Page”. Naturally the values in these examples can be changed to your liking.

The best way to make sure the credentials can not (easily) be retrieved in this way is by taking a shot at it yourself.

Thanks for all the input… I’ve been working on using sessions to keep a user logged in… things are working great so far. I’ve also beefed up security using different things I’ve picked up on my searches.

One thing I’ve been concerned about it I’ve read a lot of things about cookies not exactly being safe and obviously using the GET method isn’t either. Given that the session ID isn’t secure, I’ve been thinking of ways to confirm that the session ID is being passed by an authorized user from an authorized location. There are lot’s of global type variables that aren’t easily faked. For one I was thinking of using HTTP_HOST of $_SERVER. If the script is hosted on my web server, then it should return “mywebsite.com.” If someone is trying to use another script to hijack my script then this host will not be the same… but someone could easily add this value to their session variables in their evil script.

So what are some ways to foil attampts to hijack my sessions?

Here’s where I say: do you want to? As I said before, security and userfriendliness are two sides of the same scale. If one goes up, the other comes down. The situation you’re describing is one that would take a very motivated, very skilled hacker. Unless you’re doing a login system for a bank transaction application, or ebay-like website (for both of which I’d strongly recommend using SSL encryption), I don’t think Mr. Skilled Hacker will be too motivated trying to get behind your security lines. It depends on the level of security your application needs, really.

If I need more security, I usually use a (homemade) session ID, hash a concatenation of that ID with an expiry date timestamp and the IP address, and put this hash in a cookie, as well as a database table on the backend. That way, in order to hijack this session, the hacker should have the same IP address, as well as the cookie. If by any chance that happens, you’ll know that the hacker is on the same network.

If you’re really paranoid you could create a small login desktop program with a custom encryption algorithm that will tell your website the user is authentic.

I like that idea… how do you specify a specific session ID?

http://www.php.net/manual/en/function.session-id.php:

session_id() is used to get or set the session id for the current session.
Sponsor our Newsletter | Privacy Policy | Terms of Service