5. Security

The best resource I’ve found on PHP security is The 2018 Guide to Building Secure PHP Software by Paragon Initiative.

5.1 Password Hashing

Eventually everyone builds a PHP application that relies on user login. Usernames and passwords are stored in a database and later used to authenticate users upon login.

It is important that you properly hash passwords before storing them. Hashing and encrypting are two very different things that often get confused.

Hashing is an irreversible, one-way function. This produces a fixed-length string that cannot be feasibly reversed. This means you can compare a hash against another to determine if they both came from the same source string, but you cannot determine the original string. If passwords are not hashed and your database is accessed by an unauthorized third-party, all user accounts are now compromised.

Unlike hashing, encryption is reversible (provided you have the key). Encryption is useful in other areas, but is a poor strategy for securely storing passwords.

Passwords should also be individually salted by adding a random string to each password before hashing. This prevents dictionary attacks and the use of “rainbow tables” (a reverse list of cryptographic hashes for common passwords.)

Hashing and salting are vital as often users use the same password for multiple services and password quality can be poor.

Additionally, you should use a specialized password hashing algorithm rather than fast, general-purpose cryptographic hash function (e.g. SHA256). The short list of acceptable password hashing algorithms (as of June 2018) to use are:

  • Argon2 (available in PHP 7.2 and newer)
  • Scrypt
  • Bcrypt (PHP provides this one for you; see below)
  • PBKDF2 with HMAC-SHA256 or HMAC-SHA512

Fortunately, nowadays PHP makes this easy.

Hashing passwords with password_hash

In PHP 5.5 password_hash() was introduced. At this time it is using BCrypt, the strongest algorithm currently supported by PHP. It will be updated in the future to support more algorithms as needed though. The password_compat library was created to provide forward compatibility for PHP >= 5.3.7.

Below we hash a string, and then check the hash against a new string. Because our two source strings are different (‘secret-password’ vs. ‘bad-password’) this login will fail.

 1 <?php
 2 require 'password.php';
 3 
 4 $passwordHash = password_hash('secret-password', PASSWORD_DEFAULT);
 5 
 6 if (password_verify('bad-password', $passwordHash)) {
 7     // Correct Password
 8 } else {
 9     // Wrong password
10 }

password_hash() takes care of password salting for you. The salt is stored, along with the algorithm and “cost”, as part of the hash. password_verify() extracts this to determine how to check the password, so you don’t need a separate database field to store your salts.

5.2 Further Reading

Articles & Tutorials

Libraries

5.3 Benefits

The main benefit to using templates is the clear separation they create between the presentation logic and the rest of your application. Templates have the sole responsibility of displaying formatted content. They are not responsible for data lookup, persistence or other more complex tasks. This leads to cleaner, more readable code which is especially helpful in a team environment where developers work on the server-side code (controllers, models) and designers work on the client-side code (markup).

Templates also improve the organization of presentation code. Templates are typically placed in a “views” folder, each defined within a single file. This approach encourages code reuse where larger blocks of code are broken into smaller, reusable pieces, often called partials. For example, your site header and footer can each be defined as templates, which are then included before and after each page template.

Finally, depending on the library you use, templates can offer more security by automatically escaping user-generated content. Some libraries even offer sand-boxing, where template designers are only given access to white-listed variables and functions.

5.4 Compiled Templates

While PHP has evolved into a mature, object oriented language, it hasn’t improved much as a templating language. Compiled templates, like Twig, Brainy, or Smarty*, fill this void by offering a new syntax that has been geared specifically to templating. From automatic escaping, to inheritance and simplified control structures, compiled templates are designed to be easier to write, cleaner to read and safer to use. Compiled templates can even be shared across different languages, Mustache being a good example of this. Since these templates must be compiled there is a slight performance hit, however this is very minimal when proper caching is used.

*While Smarty offers automatic escaping, this feature is NOT enabled by default.

Simple example of a compiled template

Using the Twig library.

1 {% raw %}
2 {% include 'header.html' with {'title': 'User Profile'} %}
3 
4 <h1>User Profile</h1>
5 <p>Hello, {{ name }}</p>
6 
7 {% include 'footer.html' %}
8 {% endraw %}

Example of compiled templates using inheritance

Using the Twig library.

 1 {% raw %}
 2 // template.html
 3 
 4 <html>
 5 <head>
 6     <title>{% block title %}{% endblock %}</title>
 7 </head>
 8 <body>
 9 
10 <main>
11     {% block content %}{% endblock %}
12 </main>
13 
14 </body>
15 </html>
16 {% endraw %}
 1 {% raw %}
 2 // user_profile.html
 3 
 4 {% extends "template.html" %}
 5 
 6 {% block title %}User Profile{% endblock %}
 7 {% block content %}
 8     <h1>User Profile</h1>
 9     <p>Hello, {{ name }}</p>
10 {% endblock %}
11 {% endraw %}

5.5 Plain PHP Templates

Plain PHP templates are simply templates that use native PHP code. They are a natural choice since PHP is actually a template language itself. That simply means that you can combine PHP code within other code, like HTML. This is beneficial to PHP developers as there is no new syntax to learn, they know the functions available to them, and their code editors already have PHP syntax highlighting and auto-completion built-in. Further, plain PHP templates tend to be very fast as no compiling stage is required.

Every modern PHP framework employs some kind of template system, most of which use plain PHP by default. Outside of frameworks, libraries like Plates or Aura.View make working with plain PHP templates easier by offering modern template functionality such as inheritance, layouts and extensions.

Simple example of a plain PHP template

Using the Plates library.

1 <?php // user_profile.php ?>
2 
3 <?php $this->insert('header', ['title' => 'User Profile']) ?>
4 
5 <h1>User Profile</h1>
6 <p>Hello, <?=$this->escape($name)?></p>
7 
8 <?php $this->insert('footer') ?>

Example of plain PHP templates using inheritance

Using the Plates library.

 1 <?php // template.php ?>
 2 
 3 <html>
 4 <head>
 5     <title><?=$title?></title>
 6 </head>
 7 <body>
 8 
 9 <main>
10     <?=$this->section('content')?>
11 </main>
12 
13 </body>
14 </html>
1 <?php // user_profile.php ?>
2 
3 <?php $this->layout('template', ['title' => 'User Profile']) ?>
4 
5 <h1>User Profile</h1>
6 <p>Hello, <?=$this->escape($name)?></p>