Updated: 23 Dec. 2020

This article does not replace a good knowledge of security principles in PHP, but can give you some good advices that really boost security.
There will be nothing to copy/paste straight forward to your PHP files. But we believe that these tips and best practices will bring you long-term benefits if you understand and implement the different points according to your needs and context.

This article is the third of our series dedicated to PHP security. The first article gives you guidelines for PHP configuration, updates, data filtering and sanitization, as well as code organization.
The second article discusses protections against known and common attacks.

We will now take a look at file uploads, CRSF, cookies and security through obscurity.

Protect Your Cookies

Do not store sensitive information in cookies. Cookies are unsecure by nature, you cannot rely on them to store (temporarily or not) sensitive data.
To protect your cookies against manipulation, one good solution is to sign them, by computing a hash (with a salt), so that the server can verify their content.
The hash must be included in the cookies itself, and retrieved by the server.

File Uploads

File uploads are a very sensitive feature, since they allow users to upload files on your server. Weak implementation may allow attackers to upload PHP scripts on executable folders, giving them the ability to do almost anything.

Validate document

Since there is no bullet-proof and simple solution, a real defense in depth strategy must be adopted:

  1. Only authenticated users must be able to upload files
  2. Limit file upload files size
  3. Limit file extensions and formats
  4. Create a .htaccess file in the file uploads parent directory, specifying the list of allowed file extension, for instance with the following rules, depending on your context :
    deny from all
    <Files ~ “^w+.(gif|jpe?g|png|pdf)$”>
    order deny,allow
    allow from all
    </Files>
  5. Validate the file type (whitelist specific file types, check the mime-type)
  6. When saving files,
    • Generate the file name randomly, and do not rely on user submitted filename.
    • Use unique names
    • Verify that the file location is not already used
    • Save files outside of the website root folder
    • After having saved files, remove execute permission on the file (chmod)

The file max size can be set globally in upload_max_filesize in php.ini. If you want a specific form to allow a smaller file size, you can use the MAX_FILE_SIZE form parameter, but double-check the size with PHP itself, since that parameter can be modified by the user when submitting the file.

Additional checks on the file content:
If you are expecting an image, then you can check the size with getimagesize. If “false” is returned, then the image is not valid.
To go a bit further, the content of the file can be checked against known threats, for instance with ClamAV.

Cross Site Request Forgery (CSRF)

One good rule is to perform all state-changing action via POST requests, instead of GET requests. This will not really remove the risk of CSRF attacks, but will slightly reduce the risk of basic attacks.

To protect yourself against CSRF attacks, you must implement anti-CRSF tokens for your forms. These tokens, stored in the user’s session, will be compared with values returned by the user to validate/reject actions.
If you’re not using a framework that already implements this kind of tokens, you will then have to implement them by yourself, or use third party libraries. The OWASP has a quite good example of CSRF tokens on this page.

Security Through Obscurity

Obscurity is not a way to prevent attacks from being successful, but can really slow down attackers and hide precious information they are looking for.

You can for instance hide the version of PHP you are using (from headers), by setting expose_php to false in your php.ini.

Another example is a login form: when users submit wrong credentials, there is no need to detail why they could not connect (eg. wrong password). Simply stating that the credentials are not correct is enough, and will therefore not reveal a valid login.

Hidden safe


Security is not a one-time and easy thing to implement. First, because it depends on your particular context, but also because things are evolving quite quickly in this field, and new types of attacks emerge over time.

The different tips we provided in these articles are solving major technical vulnerabilities, but not logic flaws. As a functional designer and web developer, you must also ensure that your business logic is bullet-proof, and cannot be circumvented or abused. There is no automated and generic solution for this, apart from reviewing the logic of processes with your team.

Recent development frameworks can also help you implementing security measures, since lot of them include quite easy to use solutions and patterns. However, these security features are also easy to deactivate and any security misconfiguration can have a negative impact. It is therefore important to pay special attention to the documentation detailing how to use these security features. Frameworks are a great way to benefit from the experience of other developers, and to use maintained code.