Let’s celebrate by taking a deep look at MARIJUANA.php. The original repo is here:
https://github.com/0x5a455553/MARIJUANA
and we will be looking at this version here:
https://bazaar.abuse.ch/sample/e5fb647c470f21d5714601417768873a928f4741063fd86e4d696239eb78bf06
RE time
First take a look at the original release. This will give us a baseline to figure out what has been obfuscated and changed in recent versions.
On the left I’ve opened the github release, and on the right we have the sample we are investigating. The goal is to get our sample to where it resembles the baseline release and then we will dig into the functionality of the php shell.
The sample we are looking at is a series of charcodes. Using Cyber Chef (https://gchq.github.io/CyberChef/) we can quickly get some readable code from it. The recipe to deobfuscate the charcode to readable php is From Charcode, set the delimiter to comma, and change it from the default base 16 to base 10. This is because Javascript charcodes are represented in base 10.
Looking at the newly readable php code a few things stick out.
First we have an attempt to make the script look less conspicuous if you come across it by suppressing errors and bypass any buffering delays by setting the display_errors to 0 and output_buffering to 0.
The next obvious thing is the variable $heker
which is set to a long, obfuscated string.
And lastly, we have an eval
statement using a long chain of encodings that is run on the $heker
variable.
@eval(base64_decode(gzinflate(str_rot13(convert_uudecode(gzinflate(base64_decode(gzinflate(str_rot13(convert_uudecode(gzinflate(base64_decode($heker))))))))))));
exit;
Rather than recreate the deobfuscation order of this code in Cyber Chef, we will change the eval
to echo
and direct it to a new file. We also need to fix the apostrophes on the @ini_set
functions or just delete them. They should read like this:
@ini_set('output_buffering',0);
@ini_set('display_errors', 0);
Then we will run the php script but make absolutely certain that you have saved your change of @eval
to echo
.
php marijuana.php > marijuana_string_deobf.php
Now the php script is in a state where it resembles the original release of the Marijuana.php shell on github, as well as some interesting variables that set up a call back to an email.
When the shell is accessed, it sends an email with the URL of the script and the IP of the visitor. This suggests the attacker is keeping track of when and where their web shell is being accessed.
At this point, the deobfuscated sample now looks similar to the original released version. In this guide we will continue to deobfuscate the web shell to gain a deeper understanding of the obfuscation techniques, however at this point you have enough information to begin to clean up and understand how the compromise occurred. I will cover this at the end but please feel free to skip ahead.
Hex-code arrays
Looking at the deobfuscated script now, we have a variable named $Array
which contains an array of hex strings. Further down we fund a variable named $___ that iterates through $Array
. After that it uses uhex
which almost certainly takes the hex string and turns it back into readable text. The result of which is stored in the $GNJ
array.
$___ = count ($Array);
for ($i=0;$i<$___;$i++) {
$GNJ [] = uhex($Array[$i]);
}
Let’s take a closer look at what uhex is doing.
function uhex ($y) {
$n='';
for ($i=0; $i < strlen($y) 1; $i +=2) {
$n .= chr(hexdec($y[$i].$y[$i+1]));
}
return $n;
}
Indeed uhex is taking the hex strings and decoding them. Let’s decode them and see what they are. We will do this by simply copying the relevant code to a new php script.
<?php
$Array = [
'7068705f756e616d65',
...
];
$decodedArray = [];
$decode = count($Array);
for ($i=0;$i<$decode;$i++){
$decodedArray[] = uhex($Array[$i]);
}
echo implode("\n", $decodedArray);
function uhex($y){
$n='';
for ($i=0;$i < strlen($y)-1; $i+=2){
$n .= chr(hexdec($y[$i].$y[$i+1]));
}
return $n;
}
?>
Now lets take a look at the results:
php_uname
phpversion
chdir
getcwd
preg_split
copy
file_get_contents
base64_decode
is_dir
ob_end_clean();
unlink
mkdir
chmod
scandir
str_replace
htmlspecialchars
var_dump
fopen
fwrite
fclose
date
filemtime
substr
sprintf
fileperms
touch
file_exists
rename
is_array
is_object
strpos
is_writable
is_readable
strtotime
filesize
rmdir
ob_get_clean
readfile
assert
Oof. All kinds of dangerous commands making a well featured web shell.
Moving further through we get to the html that renders when the web shell is accessed. We get a good indicator of compromise to make an alert for. The shell takes the icon and css file from the original github release.
<link rel="icon" href="//0x5a455553.github.io/MARIJUANA/icon.png" />
<link rel="stylesheet" href="//0x5a455553.github.io/MARIJUANA/main.css" type="text/css">
The rest of the script is mechanics to process queries added to the url, which the requests are formed by the web shell, but you could also directly send to the path of the web shell.
The “MARIJUANA” web shell provides a range of features and functions that can be used by attackers for various purposes. These functions include file manipulation (uploading, renaming, removing), execution of commands (such as chmod and unzip), and manipulating file timestamps.
Cleaning up and finding the source of compromise
In order to clean up this malware, first you’ll want to immediately remove the charcode file. You’ll want to check logs for access to the path of the web shell which will reveal which commands it has executed and undo them. Then you’ll need to put some thought into how the compromise occurred. Here are some things to consider:
Think about what the file looked like to begin with, a series of charcodes in a file. How would the attacker execute the php out of the charcode?
There is likely an insecure use of eval() that is accepting user input allowing the attacker to take the charcode and execute the php script inside. Other insecure functions to look out for are system()
, exec()
, passthru()
, and shell_exec()
.
Think about anywhere the web application accepts uploads, what protections are in place there?
To prevent this, the application should have protections in place such as checking the file type and size, renaming the file, and storing the file in a location that’s not directly accessible via the web.