WordPress administrators often keep their dashboard open in the same browser they use for everyday browsing. A new attack chain shows why that habit is risky.
Researchers have documented a JavaScript loader that waits for a signed-in administrator to visit a compromised page, then uses that browser’s trusted session to install a hidden PHP backdoor on the website.
The attacker never needs the admin password, because the administrator’s own browser does the work. Recent cases point to the same pattern.
One example is an admin-triggered WordPress malware campaign that exposed more than 1.2 million websites to potential compromise.
Malware that activates only during logged-in sessions is hard to spot during routine scans, which makes it a growing concern for site owners.
Security researchers at Securonix Threat Research, Akshay Gaikwad and Aaron Beardslee, identified the malware and named the chain TRUST#GRAFT.
Their analysis shows that the JavaScript does not break the WordPress login. Instead, it checks whether the visitor is already signed in as an administrator, then reuses that session to add new code to the site. Securonix also notes that it has not confirmed how the first script reached the compromised page.
Hackers Can Abuse Logged-In WordPress Admin Sessions
The infection begins with a fake security check. The script places a full-screen frame over the page that looks like a Cloudflare “Just a moment” verification screen.
While the visitor waits, the script collects details such as screen size, graphics data, timezone, and installed plugin count. It also checks for signs of automated analysis tools.
After solving a small puzzle, the browser sends this data to a controller server, which decides whether to send the next stage. The key step follows.
The script requests the WordPress plugin upload page using the browser’s existing login cookies, then reads a WordPress security token, called a nonce, from that page.
It downloads a ZIP file named wm.zip from a staging server and uploads it through the standard plugin installation endpoint.
If the upload works, the script opens the plugins page and activates the new plugin. WordPress accepts each request because the browser is already signed in with plugin rights.
Securonix stresses that this is not a standalone login bypass. The account must already be an administrator with permission to install plugins.
Even so, the risk is serious for anyone who browses public websites while signed in to wp-admin, or who uses one browser profile for both daily browsing and site management.
Persistent PHP Backdoor Hides in Must-Use Plugins
The ZIP file contains a PHP plugin named Web Media Optimizer, version 2.1. The name suggests a harmless image or media tool, but Securonix describes it as a backdoor.
It injects remote JavaScript into public pages, turns off TLS certificate checks when it fetches its controller script, and can set an administrator login cookie for the first admin account through a hardcoded token.
.webp)
The plugin also protects its own presence. On activation, it copies itself to wp-content/mu-plugins/wmedia-recovery.php.
WordPress loads every file in that folder automatically, and those files do not appear on the normal Plugins page. Similar hidden must-use plugin malware has been reported before, and it shows why removing only the visible plugin is not enough.
Site owners should also take cleanup seriously. Removing the visible plugin, the mu-plugins copy, and any leftover remote script source is necessary to stop reinfection.
Admins should also review recent WordPress self-restoring backdoor malware cases, which show how deleted files can return.
Securonix recommends using a separate browser profile for wp-admin, signing out after suspicious activity, rotating administrator credentials, limiting plugin upload rights, and watching for new PHP files in mu-plugins.
Indicators of compromise (IoCs):-
| Type | Indicator |
|---|---|
| JavaScript loader | gerlace[.]com/0k2blyny.js |
| JavaScript loader | gerlace[.]com/j0ghlty4.js |
| JavaScript loader | vtevens[.]icu/50w2ouvx.js |
| JavaScript loader | vtevens[.]icu/x9bpnmck.js |
| JavaScript loader | caapman[.]me/cse3g1jd.js |
| JavaScript loader | http://caapman[.]me/9l56j7cg.js |
| JavaScript loader | https://caapman[.]me/4oco7gwc.js |
| Second-stage ZIP | http://caapman[.]me/p/wm.zip |
| Second-stage ZIP | https://vtevens[.]icu/p/wm.zip |
| Second-stage ZIP | https://nutmann[.]club/p/wm.zip |
| Second-stage ZIP | https://okuneva[.]sbs/p/wm.zip |
| Controller source | vilialobos[.]lol/ads.php |
| C2 domains | caapman[.]me, vtevens[.]icu, gerlace[.]com, nutmann[.]club, okuneva[.]sbs, vilialobos[.]lol |
| C2 API paths | /api/v1/8e4c615, /api/v1/f659473, /api/v1/e81929c, /api/v1/6a38418, /api/v1/76584c1 |
| JavaScript SHA256 | 19d9335e66d9d519c9068994491b1a0f8734626b5328fca9723d942b7128bc9c |
| JavaScript SHA256 | 0a3cb24e0d0c05b544a3e32affe3ea8a4ed87c0cc90e918c10b94d3b849d76fa |
| JavaScript SHA256 | 16f73adce28e3a33e98035a19721819ddac9cda130e6f1c337db6f8d8c2f95c6 |
| JavaScript SHA256 | f110e20dce8361a31332faba49e29e6afd54f8bc4913841f9bdad3cbb66c14e3 |
| JavaScript SHA256 | 85515e25894cace49286581f9436bd2da429e05bd96d39fafe1c42fbcdfcd4e7 |
| JavaScript SHA256 | 765525c4fabd01383ca3dd330dd4f4fbc931bea0724c12f553df41b48a96ca82 |
| JavaScript SHA256 | 804349f8f087588b057e942f321ec2c0a677a0374e02d47f95d43196fc4cac0a |
| JavaScript SHA256 | 4659d9648275113f7f95735d170f27f10fd6d0a4e606c5b4f6e916ddc54924ed |
| JavaScript SHA256 | 2cac894bf2cef2232247927e18acd35280065b576c5fa030b5fbad666db0afcc |
| JavaScript SHA256 | eeb182444019802abb34668bd6efc7e947c1822e95c87f9a5b5288b4331400c8 |
| JavaScript SHA256 | 2747316171bb2816b68db308162b40a47c6ddf82779d5f460a194921eb60f32c |
| JavaScript SHA256 | eb5a6c895d24fd08e3bbd74d7a0ea02600d3b7574b9761efb2876b671e8ddd39 |
| JavaScript SHA256 | 3b79b342a580dd09a5e3f907e475c3131f4005be59468a59905fc289e005806d |
| JavaScript SHA256 | 2fa9c207981e05141162b9c5cf62a86bdc6593b3a6861968e4df58f49c47da0d |
| JavaScript SHA256 | e98949a8370c5c3356a8e97f49a2f963a6126b917e1bc653890f8c79738c981d |
| JavaScript SHA256 | 07955dcb5f4f80c90ede398879589f2e369eb2d84c4975d3c8adf08433783409 |
| PHP SHA256 (wmedia-recovery.php) | 86d775c2d5cb459541cd2b0b967fac65ce20c60e483c71c9f7e108d5ad0bd564 |
| PHP SHA256 (ads.php) | 2dfa9e708fdb92e5d36080065f978e33a692c0fe813a75be9c7cdff03be51b6e |
| ZIP SHA256 (wm.zip) | 9215d17e5138cee498bb529e69b1cc7267305136535025e9b49fe173cf648720 |
| Plugin name | Web Media Optimizer 2.1 |
| Persistence path | wp-content/mu-plugins/wmedia-recovery.php |
| Hardcoded token | M2wS8mR4yP1qL7xC5vB3dG9jK6tH2z |
Note: IP addresses and domains are intentionally defanged (e.g., [.]) to prevent accidental resolution or hyperlinking. Re-fang only within controlled threat intelligence platforms such as MISP, VirusTotal, or your SIEM.
Give your SOC the alert context to stops incidents quickly. Integrate Threat Intel from 16K SOCs.

