Drupal

Jun 16, 2022 | 4 Minute Read

Drupal 8 Custom Modules: How To Write Secure PHP Code?

By: Binny Thomas, PHP/Drupal Engineer - L2

Table of Contents

Keeping security in mind from the moment one starts writing code for a custom module is vital. It is an essential part of the Drupal 8 development process. Even though it should be a common everyday activity, it can sound intimidating to those who have not done so before.

This article attempts to give a high-level overview of the different security vulnerabilities found in Drupal modules and how to write secure code keeping them in mind. The article also reviews the security aspects of a custom module and addresses vulnerabilities through a security audit.

Securing A Drupal Website

There are many ways to secure a Drupal website. One ideal way is to ensure the core, contributed modules, themes, and libraries are up to date with the latest security fixes. There are excellent modules available in the Drupal ecosystem that automatically review the security aspects of a Drupal website and provide insightful reports on what needs to be fixed.

However, if a website has a custom code specific to the particular website, it might open the door for malicious users as it does not get scrutinized by the wider public. So, if there is a plan to write PHP code for a Drupal 8 custom module, it’s important to ensure that security is incorporated right from the first stage.

Common Security Vulnerabilities In Drupal 8 Custom Module

Before beginning to write a secure code, it’s imperative to understand the common security vulnerabilities in the Drupal 8 custom module.

Note: This is not a complete list but a good starting point.

Cross-Site Scripting (XSS): Lack Of Input Sanitization

Most exploits occur through forms exposed to anonymous users. Some common attacks involve injecting Javascript code through these forms so the browser can execute them.

Input sanitization or removal of unwanted HTML tags is the standard technique to prevent this vulnerability. Drupal already comes with its sanitization functions. For example:

Xss::filter

Html::escape

For more such Drupal inbuilt functions, please read more on Sanitization Functions.

Using the Form API for automatically building forms helps to reduce the chances of such exploits. So, always ensure that all forms are built using the Form API, and all variables receiving input should pass through Drupal’s sanitization functions and methods. Also, avoid creating forms through a twig file.

Note: Drupal does not filter the values that users add at the input level. Drupal’s philosophy is to store the values submitted by the user exactly as it’s entered. The filtration happens on the way out.

Refer: Why Does Drupal Filter On Output?

Security-Oriented Task: Ensure that all forms are built using Drupal 8’s Form API, and there is a validation method before the data is submitted. As an additional measure, you should add a captcha to your forms to prevent bots from spamming.

SQL Injection: Writing SQL Queries Directly In PHP Code

SQL injection was previously one of the most common vulnerabilities across websites. Malicious users inject SQL into the site through the form fields. Although its occurrence has reduced, it is still a valid source of attacks. Use Drupal's inbuilt database abstraction layer for inserting and updating queries to remove the chances of SQL injection.

Security-Oriented Task: To prevent this vulnerability, go through the code and ensure that all insert and update queries are done using Drupal’s abstraction layer. Simple queries can be written statically through the DB abstraction layer. Using mysql_* functions directly in your custom code are highly discouraged and should be flagged for removal.

For more information, read more on Static Queries.

Missing Route Permission And Access Checks

All custom routes should be protected by permissions and access checks. Review the routes.yml and ensure that non-anonymous user-facing routes are protected with access checks.

Security-Oriented Task: Go through the custom module routes and see if any routes, specifically non-admin routes, are missing access checks. Flag the ones that are missing access checks. As a bonus, you can easily choose to automate these checks.

CSRF (Cross-Site Request Forgery)

A CSRF attack occurs when you are logged into your Drupal website and tricked into clicking a malicious entity's link. This allows the browser to make a request to the website for malicious purposes. 

These days CSRF protection is inbuilt into Drupal 8. It is now integrated into the routing access system and should be used for any URLs that perform actions without a form callback. It is possible to utilize this in the Drupal 8 custom module by placing the _csrf_token: 'TRUE’  within the module. While writing a custom module, ensure that all the routes have this particular parameter.

Security-Oriented Task: Go through all custom module routes and see if the _csrf_token parameter is present and set to true.

File Uploads: Allowing File Uploads To Unprotected Directories

If your custom module allows file uploading, the files should be placed in a specific directory, and access should be enforced by code. This should work with proper file system permissions configured in the server and Drupal’s execution privileges through .htaccess and web. config rules. It’s important to check on these as they may get missed in updates.

Security-Oriented Task: Scan the code and review all file uploads to see if it’s uploading to the folders managed by the Drupal file system. Any other place should be marked for correction. Using Drupal’s file upload field will address the common security issues.

Security Audit In Drupal 8 Custom Module

The knowledge shared above can be used to audit existing custom modules as well as during peer review and code review processes.

Tools And Techniques To Consider

There are a variety of tools that ensure a thorough and quick security audit of Drupal 8 custom modules. Let’s take a look at the tools.

Manual Inspection

If there is a small codebase, one can manually go through the above points in the custom module. Tools like grep or the IDE’s search and find options can be used to scan through the code quickly.

If the custom module is large or if there are multiple custom modules, a manual inspection can be supplemented with:

  • PHPstorms Inbuilt: PHP Inspections (EA extended)

If PHPstorm is used, one can utilize the PHP Inspections plugin for static analysis. Other IDEs should have similar plugins.

  • PHP Code Sniffer

Code Sniffer is mostly used to see if the PHP written follows coding standards. But it can also be used to find errors that indicate bad coding practices leading to security vulnerabilities.

  • Psalm

Another useful tool for security analysis is Psalm. Psalm is a free & open-source static analysis tool that helps identify code problems. For Drupal, it is necessary to install the Drupal 8 plugin.

It can also be installed via composer.

composer require mortenson/psalm-plugin-drupal:dev-master

There are a lot of configuration details involved before effectively using Psalm. For more information on this, read more on Psalm plugin.

Based on the knowledge of vulnerabilities and the tools available, it is possible to write secure code for Drupal 8 custom modules and run a security audit. Different tools can be used to supplement the manual inspection. The tools can also be combined for more effectiveness.

About the Author
Binny Thomas, PHP/Drupal Engineer - L2
About the Author

Binny Thomas, PHP/Drupal Engineer - L2

Addicted to Quora, he is a geek but also gentle and nostalgic. His idea of an enjoyable holiday is a quiet day relaxing at home. And if you find him pulling his hair, he is probably deep-diving in his thoughts!


Back to Top