I was recently looking certain random things for all Drupal sites that I know to see what information I can get from these sites and I was surprised to see that many of them do not have the basic Drupal security recommendations done. For example, I could tell the exact Drupal, PHP and Nginx versions in many cases. Some of the sites were on Drupal versions that were vulnerable. So I decided to write a checklist that if followed exactly will take care of at least the recommended best practices.
- Apply security updates immediately
Drupal core, and contrib modules that are checked in for security coverage (green tick), frequently receive security updates. If you have configured your mail settings properly, you will be notified almost immediately about this. Make sure you take action and get a hotfix rolling to get this done.
- Backup your DB and code
Frequently backup your db and code. Try to set an easy "rollback to a snapshot". For example, I often create a db and code snapshot using a bash script which saves the details into a file. If anything goes wrong, I can run the rollback script to the db and code tag that's specified in the file. There are many ways to accomplish this if you've hosted using AWS, GCP or managed platforms like Acquia, Platform.sh or Pantheon.
- Block the user id 1 . This user in Drupal is a super admin and has access to ALL configs and settings. Make sure no one can gain access by simply blocking it.
- Don't user usernames like admin, administrator for admin account 1
Use an uncommon name or random characters instead of meaningful names for the UID 1 user account.
- Use login_security, seckit, password_policy
Using login security module to block IP addresses and lock accounts with multiple wrong password attemps.
Use the password_policy module to force new users to generate a strong password.
Use modules like login_security to block people from brute-forcing your login. Better yet, use a module like secure_domain_login to move the login page to a separate domain.
- Use seckit module correctly by setting the right security headers. Some of the recommended common HTTP security headers for your Drupal website are:
Make sure in your CSP, you only allow the external sources you use. See How to correctly set Content-Security-Policy headers.
- Content-Security Policy (CSP)
Use authenticator apps, SMS or Email OTPs as a first step for logins making it more secure.
- Protect your site using a free CDN/WAF service
I use CLoudflare and their free plan is a godsend. I stop many DDOS attackers and random attackers trying to look for an opening by putting in WAF rules that block requests with certain keywords. I also hide the public IP address of my server by proxying all requests through Cloudflare. Most of the security and performance of my website is done using Cloudflare free plan.
If you do not want to purchase and install a certificate, this can be easily done using let's encrypt. It provides you a free certificate that can be easily installed by a simple python script. Make sure your redirect all your http requests to https at the web server level or CDN/WAF level or both.
- File permissions
Set the right file permissions and ownership for all your files. It is ideal that all the codebase and files folder is owned by the web user (www-data). The files folder should have 775 and settings.php should ideally have a 644 permissions. No folder or file should be writable by any user other than www-data.
- Block access to important files
Block your services.yml files, settings.php files, install.php files. You can double check all of this by writing a script and saving responses from each of these files. The install.php file gives the exact Drupal version and this must be hidden at all costs. You can set WAF rules at CDN/WAF level to save your webserver from having to respond 40x to these requests.
- Expose only 443 and 80
Close all other ports except these two using iptables, firewall (ufw) or security groups if you are using AWS. If you are using containers, make sure only the web server container is publicly available.
- Server, PHP, Nginx, MySQL updates
Make sure you consistently update your server software (Ubuntu, Debian, RedHat etc) and the LAMP packages. Like Drupal vulnerabilities, PHP, MySQL and Nginx do publish their vulnerabilities. So make sure to be ahead of them. http://nginx.org/ https://github.com/php/php-src/issues
- Hide exact versions of NginX, Apache, Drupal, PHP and so on.
Turn of nginx, apache tokens, for php "expose_php" should be off. This will stop Apache, Nginx and PHP from adding headers that specify the Nginx version. For Drupal, block the install.php path and remove the meta generator tag and X-Drupal-generator header.
- Hide your server IP address. If you have a CDN/WAF like Cloudflare, you can easily do this by proxy-ing all requests through Cloudflare.
- Set trusted host patterns in settings.php
$settings[‘trusted_host_patterns’ = [ ‘^www\.trustedwebsite\.com$’, ];
This checklist is enough to protect your sites from almost all of the possible attacks that can be made on a Drupal site. If you need help with any of these, feel free to ping me or Drupal slack or mail me.
Image is borrowed from Geekflare