4

HI, this is my first time doing this. I've read The definitive guide to form-based website authentication and http://en.wikibooks.org/wiki/PHP_Programming/User_login_systems, but I still have doubts as to whether I'm doing this correctly. Note: I'm doing this to learn, so please don't suggest a framework and php pear auth or any other related class. I just want some guidance on what I can do to improve this.

I don't need CIA style security, just something basic for a login site:

Anyway, this is how my login works:

  1. Wait for user to press Login

    if (isset($_POST['action']) && $_POST['action'] == 'Login')

  2. Does form token match token stored in session? If not die.

  3. Use php filters to validate string in username and password
  4. Hash the password (sha256) (with salt, I use the same salt for every password)
  5. Use mysqli to check for username and hashed password (LIMIT 1 in SQL).
  6. If no match is found show an error -- otherwise set the session (hashed with sha256)

At the bottom of all this I place the following, this is the line I am most worried about: My thinking is that, if the session is not set, then show the login form and exit.

 if
 (!isset($_SESSION['authenticated'])) {
     require_once 'html/login_form.html';  
     exit();   }
 // secret stuff goes here

The full code can be found here. It is still incomplete.

I will also attempt to implement this: How can I throttle user login attempts in PHP.

I am grateful for any feedback.

Community
  • 1
  • 1
john mossel
  • 2,128
  • 5
  • 24
  • 39
  • 1
    Start a transaction. Lock the row for update. Delay 5 seconds. Release the transaction. Login attempts throttled. – Ignacio Vazquez-Abrams Dec 18 '10 at 04:34
  • @john: Why are you planning to reuse your salt? You should really be using a unique salt for every password. – AgentConundrum Dec 18 '10 at 04:55
  • @AgentConundrum, would I then have to store the salt in the DB aswell? So to check if the password is correct I have have to match hash(password + salt_from_db)? – john mossel Dec 18 '10 at 05:06
  • @john: That's exactly right. It might *seem* insecure to store the salt like that, but keep in mind that a) you would have to store your "master salt" somewhere anyway, and b) using a unique salt for each password means even if your whole database is compromised somehow, an attacker would need to generate a *unique* rainbow table for *every* password in your database. – AgentConundrum Dec 18 '10 at 10:49

2 Answers2

2

This is a pretty open question as there are so many areas to pick apart. However, for average security, I would at least recommend changing the following.

Number 2: Don't use the same salt. This means if the salt is compromised so are all the hashed values. I would recommend one way encrypting the password. Users would rather reset it than know it could be reasonably decrypted.

Number 5: Don't forget about SQL Injection. Far more important than LIMIT 1. Check out mysql_real_escape_string()

Jason McCreary
  • 69,176
  • 21
  • 125
  • 169
  • So I should use filter_input and mysqli_real_escape_string. I was using mysqli_real_escape_string before, but I thought filter_input would take care of that. Thanks. – john mossel Dec 18 '10 at 05:04
  • It does seem redundant, but it would add security. If one part were vulnerable the other would still provide protection. – Jason McCreary Dec 19 '10 at 02:44
1

First, nothing is 100% secure. To make your login more secure you could add some of the following:

  1. Challenge Response - http://en.wikipedia.org/wiki/Challenge-response_authentication
  2. Three Pass Protocol - http://en.wikipedia.org/wiki/Three-pass_protocol
  3. Hash a combination of the username and password md5(password + salt + username)
  4. Use JavaScript to validate on the client then validate again on the Server
  5. Use a Database Abstraction Library to protect against SQL injection.

There are many more but it all depends on how secure you need it and how much hassle you want to put the user through. Some kind of balance is needed based on your app.

My brokerage account uses pictures and challenges before even getting to a sign-in form. This is a pain (needed on a brokerage account) but probably not so much on a blog.

Todd Moses
  • 10,919
  • 10
  • 45
  • 65