I know what many of you are thinking! PHP and security? Why bother? Just use another programming language!
Contrary to popular belief, PHP is still a viable language for building web applications. PHP is just another tool that you need to learn to use properly. Let’s discuss a few items specific to PHP that will make your site safer.
In modern PHP, you will point your web server to a directory with an index.php
file in it that will be the single point of entry for the entire site. The index.php
will load Composer packages and boot your private code to generate the response. It can be tempting to throw other PHP files in the web root for testing. However, you do not want those files to be accidentally committed and expose a problem in your app. In addition, no configuration files should go in the web root because the web server can deliver them publicly. The only static files that should be in your web root are JavaScript, CSS and image files.
You can set PHP to display errors that occur during execution with a php.ini
directive called display_errors
. The errors displayed can leak important information about your app including secrets and SQL queries. It is important to turn them off in production. In your php.ini
file, set display_errors = Off
and display_startup_errors = Off
. To still capture the errors for debugging, turn on log_errors = 1
and error_log = /var/log/php-error.log
. You can set the error log to any file path or even set it to an OS level log service.
It is common knowledge to never store passwords in plain text. However, many frameworks still use insecure hashing algorithms for converting passwords (I am looking at you WordPress). You may see some legacy articles recommending using the md5
or hash
function to hash passwords in PHP. Do not use them! The best way to hash a function in PHP is to use the password_hash
function. You can use it like this:
<?php
$hash = password_hash('iamapassword', PASSWORD_DEFAULT);
if (password_verify('iamapassword', $hash)) {
echo "The hash matches!\n";
}
The password hash function takes the plain text password and an algorithm type (PASSWORD_DEFAULT
is a safe choice). The function returns the hashed password which you can use in the password_verify
function later when the user is logging in. Password verify returns true or false depending on if the hash matches the submitted password. In case you see an article recommending salting your passwords, do not worry about salts with password_hash
. The function salts the password automatically for you.
In your PHP app, you will often have to communicate with other services or storage mechanisms. It is important that you always use encrypted connections to the services. When using curl
or soap
, always use https
URLs to APIs to verify the data in transit is encrypted. In addition, if you are using FTP, make sure you use some form of secure FTP, either FTPS or SFTP. If you don’t use any kind of secure transmission, then you might leak user data over the network activity. Using TLS also verifies the URL is what it claims to be which protects you from sending data to a bad actor.
PHP itself is often used as the template language embedded in HTML files. However, PHP does not escape output by default. Escaping prevents a bad actor from embedding malicious JavaScript in user controlled forms or pages. Consider using a custom template solution like Twig. Twig automatically escapes all output using its template syntax which protects you from forgetting to escape user data.
There is a lot more to creating a secure website than these tips, but hopefully they contribute to the overall security of your codebase. I have written about other ways to secure your website in Four Tips for a More Secure Website. Check it out if you want to learn more!