Dissecting a Joomla CMS Hack
Discovering the hack
After receiving what seems to be a quite common occurence of a reported server sending SPAM messages from Rackspace, it can be quite easily assumed it will be connected to a clients Joomla site. The issue arrises because even though we provide managed hosting for our clients, the problem still remains that Joomla has updates and patches released every few months, and the application layer is the responsibility of the client. Additionally the client's often install 3rd party extensions created by developers with little experience which can leave a corporate site vulnerable to attack.
The message from Rackspace contained a copy of one of the offending e-mail's which luckily listed the sending script: X-PHP-Originating-Script: 1001:scheduleIb8R.php
So with an "slocate
" of the file it was possible to find the folder in which it originated, where we found 6 PHP scripts where there should be none:
root@server:/home/client/public_html/images# ls -al *.php -rw-r--r-- 1 client client 11757 Mar 27 12:02 frss.php -rw-r--r-- 1 client client 23250 Mar 26 03:00 kabfimaswe.php -rw-r--r-- 1 client client 6926 Mar 27 12:02 scheduleIb8R.php -rw-r--r-- 1 client client 1025 Nov 11 23:12 sn.php -rw-r--r-- 1 client client 4334 Mar 27 20:51 stm.php -rw-r--r-- 1 client client 27854 Apr 4 22:56 txm.php
Knowing that the file names are often random, the following blog post will examine each discovered as at first glance we also have 6 different file sizes implying different scripts... intriguing:
Script 1 - File Manager: frss.php
This script is essentially a file manager, providing server details, and more worryingly it allows the user to upload any file, change permisions and delete complete folders.
Testing the file upload element it allowed me to transfer a file to the root folder of the site, but due to the server configuration and the virtualhost implementation provided by the control panel software virtualmin, the application could not upload files to outside of the client's site:
root@server:/home/client/public_html# ls -al *.jpg -rw-r--r-- 1 client client 65402 Apr 5 11:09 memory-issues.jpg
Script 2 - File Manager 2: kabfimaswe.php
This file is a replica of the above but it includes some key new features:
- Direct links to any Kernal related hacks/exploits for the specific server
- Full root server directory manipulation
- Server security information showing a lot about the server architecture
- Console access to the server allowing you execute any command
- SQL - a full database manager for MySQL and PostgreSQL
- PHP execution through web-based form
- Safe Mode bypass for transferring and reading any file owned by any user
- String Tools - literrally every tool required for encoding or hash creation. It also includes a simple lookup tool for submitting any discovered system hashes to online tools like "hashcrack".
- Bruteforce password cracker for FTP, MySQL and PostgreSQL
- Network tools for allowing the tool to bind to a specific port
- Self remove - which will cause the script to delete itself
In addition to the above, the actual file is encoded and uses the PHP function preg_replace
which leaves it with just 6 lines of code.
Script 3 - Mass Mailer: scheduleIb8R.php
This is the original culprit that alerted us to the issue. The script which can easily be found by searching on Google (pastebin) accepts multiple POST parameters that allow external scripts (and unsuspecting hacked computers) to send e-mails.
Script 4 - Joomla Link Changer: sn.php
This crafty little script uses Joomla's own configuration file to access the database and extract the sites username and password. This is a good reason to use different usernames and passwords for each virtualhost!
In addition to accessing the database directly, it has been modified to accept a POST parameter that would update any links within Joomla content with the one supplied in the post parameter. The attacker could then use this to sent unsuspecting visitors to malicious sites. The code is placed here for analysis purposes only:
Script 5 & 6 - Simplified file manager: stm.php & txm.php
This script was fully obfuscated using various encoding methods (most likely with a commercial tool PHP Lockit). The breakdown of the script went like this:
$OOO000000=urldecode('%66%67%36%73%62%65%68%70%72%61%34%63%6f%5f%74%6e%64');
This resulted in the word fg6sbehpra4co_tnd
which was then manipulated using the following sequence:
$OOO0000O0=$OOO000000{4}.$OOO000000{9}.$OOO000000{3}.$OOO000000{5}; $OOO0000O0.=$OOO000000{2}.$OOO000000{10}.$OOO000000{13}.$OOO000000{16}; $OOO0000O0.=$OOO0000O0{3}.$OOO000000{11}.$OOO000000{12}.$OOO0000O0{7}.$OOO000000{5}; $OOO000O00=$OOO000000{0}.$OOO000000{12}.$OOO000000{7}.$OOO000000{5}.$OOO000000{15}; $O0O000O00=$OOO000000{0}.$OOO000000{1}.$OOO000000{5}.$OOO000000{14}; $O0O000O0O=$O0O000O00.$OOO000000{11}; $O0O000O00=$O0O000O00.$OOO000000{3}; $O0O00OO00=$OOO000000{0}.$OOO000000{8}.$OOO000000{5}.$OOO000000{9}.$OOO000000{16}; $OOO00000O=$OOO000000{3}.$OOO000000{14}.$OOO000000{8}.$OOO000000{14}.$OOO000000{8}; $OOO0O0O00=__FILE__; $OO00O0000=0xaf4;
One of the variables in this block that is shown within the next segments eval
block, resulted in the transposition of the fg6sbehpra4co_tnd
value to read "base64_decode
" which allows the next code snippet to be revealed:
$O000O0O00=$OOO000O00($OOO0O0O00,'rb'); $O0O00OO00($O000O0O00,0x476); $OO00O00O0=$OOO0000O0($OOO00000O($O0O00OO00($O000O0O00,0x17c), 'EnteryouwkhRHYKNWOUTAaBbCcDdFfGgIiJjLlMmPpQqSsVvXxZz0123456789+/=', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')); eval($OO00O00O0);
Analysing some of the variables shows the following:
$OOO0000O0 = base64_decode; $OOO00000O = strtr $O0O00OO00 = fread $OOO000O00 = fopen $OOO0O0O00 = "/home/client/public_html/images/stm.php"
Removing the eval
and echoing the result out it was obvious that the PHP fread
was calling itself and whilst de-constructing the file I had rearranged the contents. So, I created my own extract of the code which called the original as it should so that I could continue diagnostics:
$OO00O00O0=base64_decode(strtr(fread($O000O0O00,0x17c), 'EnteryouwkhRHYKNWOUTAaBbCcDdFfGgIiJjLlMmPpQqSsVvXxZz0123456789+/=', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'));
Results in the output:
$OO00O00O0=str_replace('__FILE__',"'".$OOO0O0O00."'", base64_decode($OOO00000O($O0O00OO00($O000O0O00,$OO00O0000), 'EnteryouwkhRHYKNWOUTAaBbCcDdFfGgIiJjLlMmPpQqSsVvXxZz0123456789+/=', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')));
Which when echoed gives us the following snippet:
The features available via this script include:
- Load a file directly on to the server via a post field
- Load a file via posted file
- Run a script
- Start a script
- Restart a script
- Read a file contents
- Version info
Quick Fix
A temporary fix until the site can be rebuilt without the troublesome extensions is to disable PHP execution the images folder by adding the following lines to a .htaccess
file:
nano .htaccess # paste these lines in to the file php_flag engine off RemoveHandler .php
It should be noted though that it is now safe to assume that the server has been fully compromised at this point and there is no easy way to know if the rest of the site has been hijacked in any way. It would be any sys admins perspective that you should rebuild the server and site with the latest software versions. We've even gone as far as to create a static HTML version of a Joomla site until we had time to correctly rebuild everything - with static HTML and assuming its been cleaned of all potential file includes, you can at least buy yourself a few extra days for site reconstruction.