How Web Shells Work

A web shell is a malicious script that provides an attacker with a convenient way to launch attacks using a compromised web server. Web shells can provide a permanent backdoor into web applications and related systems. Learn how web shells work, why they are dangerous, and what you can do to detect and prevent them.

How Web Shells Work

A web shell is a malicious script that provides an attacker with a convenient way to launch further attacks using a compromised web server. Web shells are installed after successful initial exploitation and can provide a permanent backdoor into web applications and related systems. Learn how web shells work, why they are dangerous, and what you can do to detect and prevent them.

Web Shell Basics

Cyberattacks usually involve many stages and may be prepared and executed over a long period of time. When an attacker finds an entry point via a web-based vulnerability, the next step is often to install a web shell for easier remote access. A web shell is simply a server-side script that provides a user interface for the attacker. This can be as simple as a single line of code added to a legitimate page to allow the attacker to send commands via an additional query parameter, for example:

<?=`$_GET[x]`?>

Injected into a PHP file, this one line provides a rudimentary web shell that executes commands supplied using the query string parameter x. This example takes advantage of PHP syntactic shorthand – unless disabled, backticks are used to execute a string as a system shell command. This may aid an attacker in concealing the nature of the uploaded scripts from web application firewalls that might block requests containing keywords such as system() or exec(). The attacker can then visit the compromised web page and send operating system commands as values of the x parameter (if PHP and system configuration settings allow it – more on that later). More advanced web shells can include an entire GUI with a remote file manager and predefined attack payloads.

There are many ways to install a web shell script. If the target application or web server can be tricked into accepting a malicious file upload or is vulnerable to local file inclusion (LFI) or remote file inclusion (RFI), this provides an easy starting point. Attackers might take advantage of a cross-site scripting (XSS) vulnerability to gain access to an administrative account and upload a script that way. Other common vulnerabilities, such as SQL injection, can also be exploited to achieve code execution and install a web shell or append shell code to an existing file.

How Attackers Use Web Shells

Depending on local system privileges (existing or obtained through privilege escalation), attackers may be able to use the web shell just like a local command line prompt. For the minimum PHP web shell example provided above, the attacker would send URL-encoded system commands via the query parameter. Assuming a Linux/UNIX system, a typical command to get a list of user names and confirm code execution privileges would be cat /etc/passwd. To send and execute the command, the attacker would simply navigate to:

http://example.com/compromised_file.php?x=cat%20%2Fetc%2Fpasswd

Real-life web shell commands often include obfuscation to avoid detection. Once an attacker has a web shell for remote access and system command execution, the possibilities for further malicious actions are practically unlimited. Data theft and drive-by malware installation are two common uses, but web shells are also used to create and coordinate botnets for distributed denial of service (DDoS) attacks. By using a compromised remote system as a botnet command & control server, malicious hackers can cover their tracks to avoid detection. If the attacker can modify other scripts or web server configuration files, another possible attack is to redirect visitors to a malicious site.

The reason for installing a permanent command interface in the first place is often to prepare the ground for long-term activities, such as espionage or mapping out internal networks to prepare attacks on high-value systems that are not Internet-facing. This requires stealth to remain undetected for a long time, sometimes many months, so web shell installations can modify the robots.txt file to prevent search engines from indexing the compromised web page or even the whole site. Another stealth tactic is to hide uploaded and modified files in directories where there are lots of other files, preferably ones that are also frequently modified, and change the time stamp of the last file modification in order to blend in with other scripts in the same directory. A common trick is also to embed malicious code in legitimate web application files and execute the commands with an additional query parameter.

Popular Web Shell Types and Targets

Beyond minimalist shell codes used to gain an initial foothold, many more advanced web shells are available. Some of the better-known include b374k (a PHP web shell), WSO (short for Web Shell by Orb), and the advanced China Chopper web shell (commonly used in attacks originating from China). Full-fat web shells can include built-in features for file management, brute-force attacks, botnet command & control, and even detecting and removing other web shells on the compromised system.

The easiest way to set up a web shell is by simply uploading the script, so attackers like to target sites with built-in upload functionality, such as content management systems. Getting from upload to command execution requires loose server-side security, so PHP, with its permissive default settings, provides an attractive platform. After all, right out of the box, PHP allows applications to execute system commands and read their output, list system information, read and write files, spawn system processes, open network connections, and more.

Being PHP-based and the most popular content management system in the world, WordPress makes a prime target for web shell deployments, especially considering the additional attack surface of WordPress plugins. Of course, it’s not just about PHP shells – any web application that can be exploited to obtain elevated privileges could eventually have a web shell planted in it. Vulnerable web server software can provide another attack vector, as can email servers.

Detecting and Preventing Web Shells

While they can be considered a type of malware, due to various forms of obfuscation, web shells can’t easily be detected with antivirus packages or similar endpoint security software. To find a web shell, you need to look for behaviors that are unusual to a specific system, such as unexpected system command calls to cmd.exe (on Windows) or bash (on Linux/UNIX). Suspicious files may also be identified by recording file modification dates and checking for abnormal timestamps or based on network traffic that is unusual for a specific file type (such as image files sending requests).

Because web shells are so hard to find once installed, prevention is especially important. To minimize risk, follow these best practices for web server and application hardening:

  • Keep the whole web technology stack patched and updated to prevent attackers from exploiting known vulnerabilities (CVEs).
  • Use secure login credentials, especially for administrative accounts.
  • Apply the rule of minimum necessary privileges for all system and application users.
  • Harden the operating system and web server by closing unnecessary ports, disabling directory browsing, allowing execution only in specified directories, and so on.
  • Lock down default configurations for any products and technologies used. For PHP, this would include disabling dangerous functions that are enabled by default, such as eval(), system(), and exec().

Even if the system is locked down and no CVEs are found in the installed products, application vulnerabilities can still provide attackers with a foothold. To minimize exposure, you should regularly scan your websites and web applications for vulnerabilities using a high-quality dynamic application security testing (DAST) solution such as Invicti. That way, even if a vulnerability is introduced in new code or a new external dependency, you can find it and eliminate it as soon as possible.

Zbigniew Banach

About the Author

Zbigniew Banach - Technical Content Lead & Managing Editor

Cybersecurity writer and blog managing editor at Invicti Security. Drawing on years of experience with security, software development, content creation, journalism, and technical translation, he does his best to bring web application security and cybersecurity in general to a wider audience.