Threat Insight
She Sells Web Shells by the Seashore (Part II)
In part I, we introduced the notion of web shell, gave a quick presentation of PHP and looked at the loaders, minimal scripts stored on a webserver that will get and run the web shell.

Why “Shin Web Shell”?
When we looked at the code, we found the comments in Figure 1 and the link in Figure 2.


These give the handle of the person who created this web shell, and thus we decided to call it the “Shin Web Shell”. Interestingly, the comments in the code are in Indonesian, with the translation shown in Figure 3.

At the time we responded to the incident, there was no analysis of this web shell, nor was there any threat intelligence available. We thus decided to perform and publish this research.
Preparing the work
Blurring the track
In Part I, we saw that the loader for the Shin Web Shell did some trickery to set the HTTP code to 404 (“Page Not Found”) and remove some security features from PHP. The web shell itself does have similar tricks up its metaphorical sleeve. In Figure 4, we see that:
- The error logging mechanisms are disabled.
- The time limit for the execution is suppressed, allowing the script to run indefinitely.
- The output buffer is emptied.
- The caching of the response is disabled, that is reverse proxies won’t store this page.
- The HTTP code is changed three times via the function http_response_code(). After the three calls, the HTTP code the web server will return to the requester and record in the logs is “500” (“Server Error”).

What’s invoked?
The execution starts, after creating a number of functions, with the determination of what function may have been invoked. Figure 5 shows the first statements and the first two tests for variables.
When the webserver runs a PHP script, several variables are set. Two of these variables are $_GET and $_POST. Both are dictionaries1 that contains a list of keys – the parameters of the request – and the value stored. For example, making a GET request to “example.php?var1=value1” will call the script “example.php” and set the key “var1” to “value1” in the $_GET dictionary. $_POST works similarly for POST requests, though the variables are retrieved from the body of the requests, not the URL.

These tests give us a first look at the features of the Shin Web Shell, summarized in Table 1.
URL Parameter | In GET requests | In POST requests |
dir | Changes the directory the web shell is pointing to, enables browsing the file system. | Changes the directory the web shell is pointing to, enables browsing the file system. |
edit | Invokes the editor on the file passed as value and reads the content into the editor. | Writes the file loaded in the editor. The POST variable containing the content is “content”. |
chmod | No change is performed for GET requests. | Changes the permission of the file passed as value. The POST parameter containing the new permissions is “permission”. |
upload | N/A | Transfers a file from the requester to the web server, the filename is the value of the “upload” parameter. The content is retrieved from the request body. |
cmd | N/A | Executes a command passed as value to this parameter. This is described under “Command Execution”. |
rename | No change is performed for GET requests. | Renames the file passed as value, the new name is the POST parameter “new_name”. |
delete | Deletes the file passed as value to this parameter. | N/A |
Summon | N/A | Loads the adminer database manager[1]. This is described under “Accessing Databases”. |
Next is a section that detects different security solutions and features, and either bypasses or disables them. Figure 6 shows these mechanisms.

Interestingly, one of the mechanisms is Wordfence[2], a WordPress security plugin. This likely means that the author had WordPress in mind as a specific target of their web shell.
Then comes an HTTP section, which contains the code of the page. Embedded in that code are more parameters related to features, both as mentioned in Table 1 and not yet reported.
URL Parameter | In GET Request | In POST Request |
gas | Displays a form to send a test email. | Sends a test email, the recipient’s address is stored in the variable “email”. |
read | Displays the content of the file passed as value to this parameter. | N/A |
rename | Displays a form to rename a file or directory. | Renames the file passed as value, the new name is the POST parameter “new_name”. |
edit | Displays the editor. | Writes the file loaded in the editor. The POST variable containing the content is “content”. |
chmod | Displays a form to change the permissions of a file or directory. | Changes the permission of the file passed as value. The POST parameter containing the new permissions is “permission”. |
The Shin Web Shell has several functions related to files and directories management. It also has a file manager interface. The code for displaying it is shown in Figure 7. It is minimal and consists of “bread crumbs”, the different parts of the path to the current location, and a file table. They are described under “A File Manager”.

The page ends with displaying some information regarding the server (its name, IP addresses, version, disk space available …), whether certain features are available or enabled, features such as PHP’s safe mode, GCC, Perl, Python, Curl or SSH, and some information about the user under which the script is executed.
A Closer Look at Some Parts
Command Execution
Unsurprisingly, the Shin Web Shell enables the requester to execute a command locally on the server, if the necessary privileges are present. For example, the account under which the web service runs must have permissions to read and execute the file, in addition that the directory in which the executable is present allows execution.
The function tries all PHP methods for executing system commands in order. Figure 8 shows the code responsible for using proc_open() to run the command. If that succeeds, the function exits after having read STDOUT and STDERR, the output streams for the process, and returning the command output.

If proc_open() fails, the code tries to run the same command using shell_exec(), as shown in Figure 9. Again, if the call succeeds, the function exits, returning the command output.

If that also fails, the code tries to use, in order, exec(), passthru(), and then system() to run the command. If all these fails, the function exits with an error message. This is shown in Figure 10. At each step, if the call succeeds, then the function exits, returning the command output.

Accessing Databases
If the requester clicks on the button called “Adminer”, the Shin Web Shell downloads Adminer version 4.8.1 (at the time of our analysis), writes it on the disk and gives the link to the requester.
From the Adminer web site, this is a database management tool written in PHP. It can natively access MySQL, MariaDB, PostgreSQL, CockroachDB, SQLite, MS SQL, and Oracle, and has the possibility to add a few more databases by using driver plugins.
First, the requester would have to get some credentials for the database: these can be default credentials or retrieved from a configuration file, a typical case is from a “config.php” file. With the Shin Web Shell, this can be done either by browsing the file system and reading the interesting-looking files or by issuing a system command, for example “grep -rFi ‘username’ /*”.
With the credentials, the requester can connect to the database and pass SQL commands. An immediate possibility comes from the feature “Export table structure, data, views, routines, databases to SQL or CSV”. Yes, this is dumping the database prior to exfiltration.
A File Manager
Part of the Shin Web Shell is a “file manager” like interface, that enables browsing the server’s file system.
The first part is the “bread crumbs”, that is the path elements, such as “D: / Users / JohnDoe / Documents”. This enables quick navigation by clicking anywhere in the path and going directly to the corresponding directory. The code is fairly straightforward and does not deserve more analysis.
The second part is a “file table”. Another comment in Indonesian is present before the function definition, as shown in Figure 11.

The table consists of five columns:
- Name
- Type
- Size
- Permission
- Actions
The “Name” and “Size” are obvious. The “Type” is set to “Folder” if the object is a directory, otherwise it is flagged as “File”.
The “Permission” is the POSIX file system permissions expressed in octal[3]. There are a couple of notes.
- If the server is running a Microsoft Windows OS, the permissions won’t be correctly rendered.
- Additional (“extended”) permissions won’t be displayed.
The author added a visual indication, with the code shown in Figure 12: the permission is written in red if the user has the permission to write the file or to create/modify files in the directory, otherwise the permission is written in green.

The “Action” column presents the possible options. The code is shown in Figure 13.

For both files and directories, the possible actions are renaming, changing permissions and deleting, calling the Web Shell with the parameter “rename=”, “chmod=”, and “delete=” followed by the name of the object, respectively.
In addition to the actions above (rename, permissions change, deletion), filesystem objects identified as “files” have an additional “edit” action, corresponding to the parameter “edit=”.
It is important to note that none of the functions used is limited to the web directories: the entirety of the file system can be browsed, as long as the user under which the web server runs has permissions to access. For Windows, this includes accessing the different drives, though the requester would have to manually create the parameter “dir=”: the code is heavily geared toward Un*x/Linux, where all the mounted filesystems can be accessed under the root “/”.
Encoding parameters
The Shin Web Shell does not obfuscate the parameters passed, neither in the GET nor in the POST requests. These are simply urlencoded[4], for example the string “Hello, World!” is converted to “Hello%2C%20World%21”.
As a result, the GET parameters – passed as part of the URL – are easily readable from the logs.
Final Tally of Features and Conclusion
The Shin Web Shell is a small but efficient web shell with several features.
- File system browsing
- File edition
- File upload
- File and directory renaming
- File and directory permission change
- File and directory deletion
- Command execution
- Test mail sending
- Database management (via Adminer)
From a dissimulation standpoint, this web shell does not put much effort into obfuscating the data the requester submits, which results in that information being available – at least for the data passed in the URL – in the logs.
The file browsing capabilities combined with the database management plugin mean this web shell can be very effective at accessing and dumping databases once the credentials have been retrieved from the relevant configuration files.
An Unknown Web Shell
In the next and last part of this series, we will have a look at a Web Shell that does not have any indication of origin or author.
References
[1] “Adminer”, Adminer – Database management in a single PHP file
[2] “Wordfence security plugin” , WordPress Security Plugin | Wordfence, by WordPress
[3] SLES 12 SP5 | Security and Hardening Guide | Access Control Lists in Linux
Stay ahead with cyber insights
Newsletter
Stay ahead in cybersecurity! Sign up for Truesec’s newsletter to receive the latest insights, expert tips, and industry news directly to your inbox. Join our community of professionals and stay informed about emerging threats, best practices, and exclusive updates from Truesec.