Threat Hunting Detecting Web Shells on Servers

Threat Hunting: Detecting Web Shells on Servers

Hello, friends its been some time since I have published any new article today we will be talking about “Threat Hunting Detecting Web Shells on Servers“. In most cases, any cyberattack that wants to target an online business will first target their web applications.

As getting in the web application is relatively easy and can be done without raising any alarms. So the ability to detect the web shell is very crucial for cybersecurity experts. In order to stop the propagation of the attack any further in the infrastructure.

The first thing that you need to do when you are looking for web shells is to analyze the file in the webserver to look for any recently modified files or the files that were newly created.

That can really shortlist the possible number of files that you will normally have to look at. A web shell is used by the attackers for creating socket connections over the network between the attacker and compromised systems and executing system commands or other malware commands, file transferring issues. So If we search a web shell we can search socket scripts like fsock, socket, sock, eval, base64, rot13, shell, exec, system, os keywords.

The other approach that can also be used is to check for the network activities to and from the server if you already have a system in places like Snort or any other network-based intrusion detection system they save the pcap file for all the traffic to and from the network.

You can run an analysis on that pcap files to find any malicious traffic that was being sent from your server like those:

Also Read: Setup your own VPN server

NON-DNS traffic pass through TCP 53. port. When I follow the stream I come up a shell connection;

Reference: Threat hunting

You can see the shell being uploaded if the traffic is unencrypted.

Now what you can do for identifying recently changed files you can run the following command to calculate the hash of all the files that are in your web server in the start:

for file in $(ls); do echo $(md5sum $file); done > original.txt

And then if you suspect that there is some web shell on the server you can again calculate the hash for the files to see if there was any change.

for file in $(ls); do echo $(md5sum $file); done > compare.txt

After that, you can simply compare both files to see which files have a changed hash and you haven’t modified those files or it was not created by you:

diff original.txt compare.txt

In this way, you can narrow down your search to identify malicious web shells that might be present on the server.

Also Read: What is a Security Operations Center (SOC)?

Other things that can also be done are the following:

Data Required

Web server logs (apache, IIS, etc.)

Collection Considerations

Collect from all web servers, and ensure that parameters are collected.
POST data should be collected.

Analysis Techniques:

Stack counting
String matching


  • Stack by page hits — pages with few hits are a typical sign
    • Add more fidelity by combining views from below (none of the above is giving higher fidelity, one, two or all):
      • No referer from client
      • Stack by unique visits per IP — most only visit the web shell (no other page hits, no js, no images, etc.)
        • this isn’t true of injected web shells (where they are injected into an existing page)
      • Stack by UA uniqueness. This is not always rock-solid, but good, because many web shells have client software that sets the UA and many don’t change the default
  • Look for parameters passed to image files (e.g., /bad.png?zz=ls)
  • More specific to inject web shells that inject into an existing page:
    • Stack by parameter counts per page — web shells that create new params on an existing page
      • Again, you can look if referer is missing, UA uniqueness

Scanning for Web Shells:

Now the next method that can be used is by using an automated script that looks at all the files and finds out if there are any web shells present on the server. This is done by looking for a different function that is generic to all the web shells like:

  • PHP functions like exec()shell_exec(), etc.
  • asp(.net) functions like eval()bind(), etc.)

There are different open-source script on GitHub that can be used for running these scan and saving a lot of time a few are:

About web shell scan

Web shell scan is a cross-platform standalone binary that recursively scans through a specified directory with either user-defined or default regex. Web shell scan utilizes a pool of go routines (10 total) to read from a channel and speed up the scanner. Note, the regex supplied with the scanner isn’t 100% and does not guarantee it will find every web shell on disk.

This tool is related to the following write up:

To test the effectiveness of the scanner, it was tested against the tennis web shell repo:


None! Simply download the binary for your OS, supply the directory you wish to scan and let it rip.

Running the binary

Running webscan with no arguments shows the following arguments:

/Users/beastmode$ ./webscan
    -dir string
      	Directory to scan for web shells
    -exts string
      	Specify extensions to target. Multiple extensions should be passed with pipe separator (asp|aspx|php|cfm). Default is all extensions
      	If a match is found, grab the raw contents and base64 + gzip compress the file into the JSON object.
    -regex string
      	Override default regex with your own
    -size int
      	Specify max file size to scan (default is 10 MB) (default 10)

The only required argument is dir, but you can override the program defaults if you wish.

The output of the scan will be written to the console. The example below (For best results, send stdout to a JSON file and review/post-process offline):

/Users/beastmode$ ./webscan -dir /Users/beastmode/webshell-master

{"filePath":"/Users/beastmode/webshell-master/xakep-shells/PHP/wacking.php.php.txt","size":142739,"md5":"9c5bb5e3a46ec28039e8986324e42792","timestamps":{"birth":"2019-02-03 02:02:22","created":"2019-03-17 13:18:52","modified":"2019-02-03 02:02:22","accessed":"2019-04-25 01:19:47"},"matches":{"eval(":2}}

### With STDOUT:

/Users/beastmode$ ./webscan -dir /Users/beastmode/webshell-master -raw_contents=true > scan_results.json

Once the scanner finishes, it will output the overall scan metrics to STDOUT, as shown in the example below:


Custom regex

You can also supply your own regex if you have some specific regex pattern you’re looking for:

./webscan -dir=/opt/https -regex="eval\\(|cmd|exec\\(" -size=5 -raw_contents=true -exts=php|jsp

Building the project

If you decide to modify the source code, you can build the project using the following commands:

cd <path-to-project>
## Windows
GOOS=windows GOARCH=386 go build -o webscan_windows.exe main.go
## Linux
GOOS=linux GOARCH=386 go build -o webscan_linux main.go
## Darwin
GOOS=darwin GOARCH=386 go build -o webscan_darwin main.go


Also Read: What is Security Information and Event Management (SIEM) Tool?



A Python open-source toolkit that helps you find malicious, hidden and suspicious PHP scripts and shells in a chosen destination, it automates the process of detecting the above.


The main purpose of BackdoorMan is to help webmasters and developers to discover malicious scripts in their site files, because it is quite common for hackers to place a back-door on a site they have hacked. A back-door can give the hacker continued access to the site even if the site owners change account passwords. Back-door scripts will vary from 100s of lines of code to 1 or 2 lines of code and can be merged in hundreds of files which makes it very hard to discover it, especially if the back-door is inactive. There are common ways and tools that can be used including grep, but BackdoorMan automates all the above as described earlier and make it, even more, easier (at least I hope so).


  • Shells detect by filename using a shell signature database.
  • Recognition of web back-doors.
  • Detect the use of suspicious PHP functions and activities.
  • Use of external services besides its functionalities.
  • Use of nimbusec shellray API (free online web shell detect for PHP files
    • Very high recognition performance for web shells.
    • Check suspicious PHP files online.
    • Easy, fast and reliable.
    • Classification for web shells with behavior classification.
    • Free service of nimbusec.
  • Use of VirusTotal Public API (free online service that analyzes files and facilitates the quick detection of viruses, worms, trojans and all kinds of malware), can be useful in our situation.
  • Use of UnPHP (The online PHP decoder: UnPHP is a free service for analyzing obfuscated and malicious PHP code) Very useful in our situation.
    • Eval + gzinflate + Base64.
    • Recursive De-Obfuscating.
    • Custom Function and Regex Support.

That’s it for this article and if you have any questions do comment down below.