Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How secure is my PHP login system?

You should include some kind of timeout or failover to prevent against brute-force attacks. There are a number of ways to do this, including IP-based blocking, incremental timeouts, etc. None of these will ever stop a hacker, but they can make it much more difficult.

Another point (which you haven't mentioned, so I don't know your plan) is failure messages. Make failure messages as vague as possible. Providing an error message like 'That username exists, but the passwords did not match' might be helpful to the end-user, but it kills login functionality. You just converted a brute-force attack that should take O(n^2) time to O(n) + O(n). Instead of needed to try every permutation in a rainbow table (for example), the hacker just tries all values for username (with a set password) first, until the failure message changes. Then, it knows a valid user, and just has to brute force the password.

Along those lines, you should also make sure that the same amount of time elapses when a username exists and doesn't exist. You are running additional processes when a username actually exists. As such the response time would be longer when a username exists vs when it doesn't. An incredibly skilled hacker could time page requests to find a valid username.

Similarly, you should make sure that, in addition to expiring cookies, you also expire the sessions table.

Lastly, in the get_user_info() call, you should terminate all open sessions if there are multiple concurrent, active logins. Make sure you timeout sessions after a set amount of inactivity (like 30 minutes).

Along the lines of what @Greg Hewgill mentioned, you haven't included any of the following:

  • SSL/encrypted connection between Server-Client
  • Other transport protocols you much be using to process authentication (like OAuth)

You server is secure, but it doesn't matter how awesomely secure your algorithm is if someone can read the data that's exchanged (MITM). You should make sure you are only communicating over an encrypted protocol.


...run the user entered password through the encrypt function...

So how does the password get from the browser to the server? You haven't mentioned protecting against man-in-the-middle attacks.


This code...

function encrypt($plain_text, $salt) {
    if(!$salt) {
        $salt = uniqid(rand(0, 1000000));
    }
    return array(
        'hash' => $salt.hash('sha512', $salt.$plain_text),
        'salt' => $salt
    );
}

...is bad. Use the new password API and be done with it. Unless you are an expert, you should not try to design your own authentication system. They are extremely difficult to get right.

In order to log the user in after their credentials passed I generate a random unique string and hash it:

Just let PHP handle session management. rand() and mt_rand() are both very insecure random number generators.


It looks like the code you created is not testable through automated unit and integration tests. This makes it hard to spot any errors that might be included in your implementation over time and while running in a production environment.

This normally leads to security issues, because the security of a strict and correct execution and sane data handling is not tested/verified.

(It's just another point on the list, see as well the answer about how to secure the transport layer, also you have not specified how you protect your session data from being tampered.)

  • Authentication Cheat Sheet
  • Session Management Cheat Sheet