Checking Your WordPress Instance Has Not Been Compromised

by 11th October 2021Platforms, Technological Thoughts, Wordpress

A slight, but pertinent, digression from the subject at hand: I have been looking recently at implementing Content Security Policy headers on all the websites managed by europoint, and best practice recommends that the unsafe-inline and unsafe-eval parameters are not used.

Unfortunately, WordPress and any number of plugins will incorporate inline style sheets and JavaScript into web pages, which makes the use of these parameters all but mandatory. Calls made to JQuery, a widely used JavaScript framework in WordPress, often use inline evaluation extensively.

A solution, which has been discussed at length by many, is to implement a unique nonce or hash to the inline code, which validates that the code is legitimate.

The difficulty is in applying such nonces or hashes to a CRM, which in essence, relies on dynamic changes and updates.

This comes to the crux of this article. The result is a bash script to validate that your WordPress install, including themes and plugins have not been tampered with.

A Solution For CSP and WordPress?

In a word, no. I quickly realised that attempting to generate a nonce unique to your instance of WordPress that could be validated as legitimate, would not work.

The concept had been to generate a unique nonce based on the fact that your WordPress installation, including core, themes and plugins were valid and unchanged, which could then be used for any inline scripts.

Unfortunately, I have a number of paid-for and custom plugins that are downloaded directly from the vendor, which are not available on the WordPress.org plugin site.

This means that there is no centrally available list of checksums for all WordPress plugins.

Then too, there are modifications which are made by various plugins to core files (even if it is just renaming the readme.html for security purposes) which break the validation.

So, What’s the Point of This Article?

As I had started down the road already, I decided to write a bash shell script that would quickly tell me if a WordPress installation had been tampered with, and highlight anything that deviated. There are plugins that can do this, but if you want a command line option, this is it.

The script pulls the MD5 hashes from the wp-md5.com website and runs a check, first against WordPress Core, then against any themes and plugins that you have installed and informs you if they match or of any deviations.

Two provisos: The script needs curl and the WordPress CLI to be available. Just place the script in the WordPress home directory, make sure it is executable by you (chmod 700 wp-validate.sh) and call it by typing ./wp-validate.sh.

wp-validate.sh

#!/bin/bash
#================================================================================
#(C)2021 Europoint Communications ltd
#Title       : wp-validate.sh
#Version     : V1.00
#Author      : Matthew Cunliffe (https://www.europoint.uk)
#Description : Script check Wordpress Core, Plugins and Themes against checksums
#Dependencies: curl, wp CLI
#Usage       : ./wp-validate.sh
#================================================================================
# Version history:
#2021.09.21 Script check Wordpress Core, Plugins and Themes against checksums
#================================================================================
#Script to be placed in Wordpress Home directory

#CONSTANTS#
GREEN='\e[0;32m'
YELLOW='\e[0;33m'
RED='\e[0;31m'
GREY='\e[0;37m'

core_md5 () {
#Checks core files against MD5 checksums

	#Retrieves the Wordpress Core Version
	core_version=$(wp core version)
	#Retrieves the checksums for Wordpress core files
	core_url="https://wp-md5.com/core/${core_version}/"
	eval curl -s "${core_url}" |  md5sum -c --status -
	#Outputs the result of the validation and lists any invalid files
	case $? in 
		0)
			printf "$GREEN* Wordpress %s is OK.\n" "${core_version}"
			;;
		1)
			printf "$RED* Wordpress %s validation has failed.\n" "${core_version}"
			printf "$GREY$(curl -s "${core_url}" |  md5sum -c --quiet -)\n" 
			;;
	esac
}

ext_md5 () {
#Checks plugin and theme files against MD5 checksums
	#incoming parameter of either "theme" or "plugin"
	ext="$1"
	cur_dir=$PWD
	ext_dir="${cur_dir}/wp-content/${ext}s"
	#Retrieves the checksums for theme or plugin files
	ext_checksum_url="https://wp-md5.com/${ext}"
	#For each theme or plugin,  carries out the file validation and lists any invalid files
	while IFS="," read -r ext_name ext_version
	do
		#Checks the theme/plugin directory exists
		ext_url="${ext_checksum_url}/${ext_name}/${ext_version}/"
		if [[ -d ${ext_dir}/${ext_name} ]]
		then
		{
			cd "${ext_dir}"/"${ext_name}" || exit
		}
		else
		{
			printf "$RED* %s directory not found in %s/\n\n" "${ext_name}" "${ext_dir}"
			continue
		}
		fi

		#Checks if the checksums are available. If the theme/plugin is not held in the Wordpress.org
		#website, then we can't validate the checksums
		if [[ $(curl -s "${ext_url}") == *"You are a dummy"* ]]
		then
		{
			printf "$YELLOW* No checksums found for %s, version %s.\n" "${ext_name}" "${ext_version}"
			continue
		}
		#Outputs the result of the validation and lists any invalid files
		else
		{
			eval curl -s "${ext_url}" |  md5sum -c --status -
			case $? in 
				0)	
					printf "$GREEN* %s, version %s is OK.\n" "${ext_name}" "${ext_version}"
					;;
				1)
					printf "$RED* %s, version %s validation has failed.\n" "${ext_name}" "${ext_version}"
					printf "$GREY$(curl -s "${ext_url}" |  md5sum -c --quiet -)\n\n" 
					continue
					;;
			esac
}
		fi
	done <  <(wp "${ext}" list --fields=name,version --format=csv | tail -n +2)	
	cd "${cur_dir}" || exit
}

main () {
	printf "$GREY\n\n=====Running Validation Check for Wordpress Core=====\n"
	core_md5
	printf "$GREY\n\n=====Running Validation Check for Wordpress Plugins=====\n"
	ext_md5 plugin
	printf "$GREY\n\n=====Running Validation Check for Wordpress Themes=====\n"
	ext_md5 theme
	printf "$GREY\n\n=====Wordpress Checksum Validation Complete=====\n"
}

main
Matthew Cunliffe

Matthew Cunliffe

Author

Matthew is an IT specialist with more than 24 years experience in software development and project management. He has a wide range of interests, including international political theory; playing guitar; music; hiking, kayaking, and bouldering; and data privacy and ethics in IT.

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *

Share this post