- Protecting Passwords
- Registration
- Logging In
- Logging Out
- Managing Passwords
- Improving the Security
Improving the Security
The user accounts system in this example demonstrates a good approach to security. For starters, users are forced to use both letters and numbers in their password and at least one letter in each case. You could improve the security by requiring at least one nonalphanumeric character and by increasing the minimum length. Security is inversely proportional to convenience, so you would make these changes knowing that you’ll annoy some of your potential customers. I also chose not to implement a “remember me” option because requiring that users log in each time they visit the site makes for better security (although, again, that requirement is an inconvenience).
As another safeguard, the passwords are securely hashed before being sent to the database. And the only user account type that can be created through the registration process is the standard member; there’s no way to trick the system into creating an administrative account.
Another obvious and relatively easy way you can improve the security of the site is to implement SSL for the registration and login processes. To do so, change the link to the registration page to 'https://' . BASE_URL . 'register.php'. That form will be loaded via HTTPS, and the form data will be posted back to the server via HTTPS, too. In fact, with nothing but relative links in the site, everything will be HTTPS from that point forward until you create a link that returns to an HTTP connection.
Serving the login form over HTTPS is trickier, because the form is included by other pages. Your options are to serve every page over HTTPS, which isn’t ideal, or to create a separate login page.
As mentioned before, you could implement an activation process as part of the registration, in which case the customer would be sent to PayPal after activating the account, not after first registering. You could also send an email when a password change is requested and only by clicking the link in that email would the user have her password reset. I’ll explain this approach in Part 4.
Because this system relies on a login to authenticate the user, much of its security depends on using sessions and a cookie (for storing the session ID in the browser). Limiting the life of the cookie, changing the session name (which is also the cookie’s name), and tweaking the other cookie parameters can all increase the site’s security. You can even send the cookie only over SSL, but that would require using SSL for every page once the user logged in.
For the session itself, one recommendation that I had in Chapter 2, “Security Fundamentals,” was to change the session storage directory when using a shared host. You can also shorten how quickly the session expires, as well as how quickly the session cookie expires.
Another nice security feature is the prevention of session fixation attacks when an administrator logs in. To recap that scenario and code, a session fixation attack is when a malicious user, Alice, starts her own session on your site, quite legitimately. She then gets administrator Bob to visit the site using that same session ID, normally by getting Bob to click a link with the session ID embedded. When Bob logs in to the site, that same session will now be associated with an administrative account, giving Alice administrative access through her browser and existing session.
Preventing such attacks is quite simple: Change the session ID using the session_regenerate_id() function:
if ($row['type'] === 'admin') { session_regenerate_id(true); $_SESSION['user_admin'] = true; }
By doing so, when Bob logs in, his session ID will change, meaning Alice’s legitimate session won’t be updated to reflect Bob’s administrative status.
You’ll need to call session_regenerate_id() before storing any session data, because by passing a value of true as the first argument to the function, any existing session data is also destroyed. Arguably, this same approach could be used to heighten security when any user logs in. You could also regenerate the session ID when major account changes occur, such as resetting the password.
A last consideration is that access to site content in this example will be determined by dates without times. With the sessions as written, the worst thing that could happen would be that a user whose account expires today is allowed to continue accessing site content for some minutes or hours into tomorrow. But even that is only true if the user keeps his session active. Not a huge concern, in my opinion.