Web Hosting

How Attackers Disguise a Web Shell as a CSS File, and How to Check Your Own Server

Illustration of a disguised file icon with a hidden warning glow, representing a web shell hidden as a legitimate-looking file

A file that ends in .css isn’t supposed to do anything except style a page. That assumption is exactly what a recently documented attack against Citrix NetScaler appliances exploited: once attackers had a foothold, they reconfigured the server so that requests to what looked like a normal stylesheet path were secretly routed to a PHP web shell instead, according to a writeup published by The Hacker News.

NetScaler is enterprise load-balancing and application-delivery hardware, not something a typical small business website runs directly, so this isn’t a “your hosting account is affected” warning. It’s a genuinely useful case study, though, because the trick at the center of it (making a malicious file look exactly like a boring static asset) is one of the oldest and most effective moves in web shell deployment, and it works just as well on a compromised WordPress install or a shared hosting account as it does on a piece of networking appliance.

What Actually Happened in the Reported Attack

According to the writeup, attackers placed a PHP web shell at a path designed to blend into NetScaler’s own login directory structure, then modified the server’s Apache configuration file to enable PHP execution for files that would otherwise be served as static content. Any request to that path looked, at a glance, like ordinary traffic to a stylesheet resource. From there, the reported payloads included a Perl script and a Python-based reverse shell staged for retrieval, plus outbound connections to a small set of attacker-controlled IP addresses used both to host those payloads and to receive a reverse shell connection back out.

The attackers also edited the appliance’s own configuration file to create a new local account with full administrative privileges, a step that’s worth noticing on its own: once a web shell gives an attacker code execution, the very next move is usually to create a persistent, legitimate-looking account rather than keep relying on the shell itself, since a new admin account survives a lot of cleanup steps that a single malicious file wouldn’t.

The Pattern That Applies Far Beyond NetScaler

Strip away the NetScaler-specific details and what’s left is a pattern that shows up constantly in compromised WordPress sites, PrestaShop stores, and plain shared hosting accounts: a malicious script given a filename and extension chosen specifically so it doesn’t stand out during a quick glance through a file manager. Instead of shell.php, it’s style-cache.css.php, or a file dropped into an /images/ or /uploads/ folder with a name that looks like a normal plugin asset. Instead of a new NetScaler admin account, it’s a new WordPress user with Administrator rights, or a new FTP account added to a hosting control panel that the site owner never created.

That’s the actual reason this incident is worth reading about even if you’ll never touch a NetScaler box: the mechanics of “disguise it as something boring, then create a backup account for persistence” are universal, and most website owners have never actually looked for either one on their own hosting account.

Five Concrete Things to Check on Your Own Hosting Account

Most guidance on web shell detection assumes a security operations team with log aggregation and file integrity monitoring tools already running. A small business site owner doesn’t have that, but a handful of manual checks cover a surprising amount of the same ground.

Sort your file manager by date modified, not by name. Most hosting control panels let you do this directly. A web shell has to land somewhere, and unless an attacker specifically fakes timestamps, it shows up as a file modified far more recently than everything around it, sitting in a folder (uploads, cache, a theme’s assets directory) that normally never changes on its own.

Look for executable file types in folders that should only hold static assets. An /uploads/ or /wp-content/uploads/ directory has no legitimate reason to contain a .php file. If your hosting control panel lets you search by file extension within a directory, that single search catches a large share of real-world web shell placements.

Review your admin and FTP/SFTP account lists for anything you didn’t create. This is the single most important check, directly inspired by what happened in the NetScaler case: an attacker who’s established code execution will frequently create a new privileged account rather than keep using the original entry point, because the entry point might get noticed and closed. A new WordPress Administrator you don’t recognize, or an FTP account added outside of when you last set one up, is a stronger signal than almost anything else on this list.

Check your site’s outbound behavior if your hosting plan gives you any visibility into it. A web shell that’s actively being used for a reverse shell connection, exactly like the Python payload described in the NetScaler incident, needs to reach out to an external server to do it. Not every hosting plan exposes this kind of monitoring, but if yours does (through a security add-on, a WAF dashboard, or server-level logs), unexplained outbound connections to unfamiliar IP addresses are worth investigating immediately rather than dismissing.

Scan your .htaccess file and any cron jobs for anything you didn’t add. Attackers who want their access to survive a cleanup attempt often add redirect rules or scheduled tasks that silently restore a web shell even after it’s deleted. A .htaccess file with rules you don’t remember writing, or a cron job pointing at a file path you don’t recognize, both deserve a second look.

If You Actually Find a Web Shell

Finding a suspicious file is not the same as having fully removed a compromise. The realistic next steps are: change every password associated with the account (hosting control panel, WordPress admin, FTP, database) before doing anything else, since a shell that’s already run arbitrary code may have already read your existing credentials. Then remove the suspicious file and any account you didn’t create, and only after that, restore from a clean backup if one exists from before the compromise. Skipping straight to “delete the file and move on” is how the same shell quietly reappears a week later through the backup account nobody noticed yet.

If your hosting plan includes any kind of malware scanning or a security team you can actually reach, this is exactly the moment to use it rather than handle a suspected compromise entirely alone. A host that offers real service-level guarantees around support response time is worth knowing about before an incident, not just after one.

The Broader Lesson

The specific CVE behind the NetScaler attack will get patched, the specific IP addresses will go stale, and the specific filenames will change in the next version of this attack. What won’t change is the underlying logic: disguise the malicious file as something boring, then create a quiet, legitimate-looking way back in. Running through the five checks above once, even on a site that’s never shown any sign of trouble, takes under fifteen minutes and is the closest thing a small business site owner has to the file-integrity monitoring a larger security team would run automatically.