Tuesday, October 26, 2010

Reverse engineering an "encrypted" Joomla! plugin

On extensions.joomla.org a lot of extensions are offered worthwhile using. Most of them are released under the GNU/GPL and free to use, others are offered under a commercial license - I don't have a problem with this, because for me the functionality is more important than the amount of money I have to pay.

Open source or not

But one thing which I find very important is the openess of the PHP-code. If an extension is GPL-ed, the code is open source which enables me as programmer to fix problems myself instead of relying on other people to fix it for me. It allows me to solve problems much quicker.

With commercial extensions however there are two variations: Extensions which are both commercial as open source and extensions which are both commercial as closed source. I prefer the open source extensions, but sometimes you're just stuck with closed source because of the functionality it sometimes offers. I always cross my fingers and hope that I don't bump into a problem that makes me call some helpdesk-guy that doesn't understand a bit of the problem.
The website is down

Now something happened which made me reconsider my point on closed source extensions (for the worse): The website was down. I have full access to the webserver, so I logged in through SSH to have a look at the Apache error-log. There I quickly discovered the problem. Some kind of Joomla! plugin gave a huge timeout.

The Joomla! plugin in question was a system plugin and depended on a helper-file. Somehow this helper-file tried to reach another remote site. And because this other remote site was down as well, the Joomla! plugin was waiting indefinitely for a response and so did my website. No timeout was being given.

I quickly logged into the Joomla! Administrator, navigated to the Plugin Manager and disabled the plugin. Hmm, the website was still down. Appearently disabling the plugin from within the Joomla! backend did not actually disable the plugin itself. With a steady hand I removed the plugin-files. The website was up again.

Next, I deciced to do a full audit on this plugin. What was causing the problem? And more importantly, why did it not give a timeout when trying to reach the remote site - for a proper PHP-script it seemed to be the most responsible thing to do.
A first glance at the evil Joomla! plugin

At a first glance the plugin looked very cool. The backend did not have any parameters, it showed an HTML description which was displayed just as plain text and not as HTML, and the plugin title did not follow the plugin naming conventions ("System - My Plugin"). But sometimes I'm just too picky about these things. Instead of becoming to frustrated I had a look at the code instead.

The main PHP-script is written following the JPlugin-class standard, which is a clear way of writing your own plugin. However the main file included a helper file, even when the plugin itself was disabled. That was a big mistake: The helper tried to fetch content from a remote site, which was down. But it tried to do this, regardless of the state of the plugin. If the plugin would be disabled, there was no need for this action anyway.

...
include_once( dirname( __FILE__ ) . '/evil.helper.php' );
...
class plgSystemEvilplugin extends JPlugin
...


License and reverse engineering

The Joomla! plugin was mentioning (in the source code) a copyright but not a license. On the website I could not find any word of the license under which the source code was distributed. Now, Joomla! is released under the GNU/GPL and officially all extensions that extend Joomla! should fall under the GPL as well, and thus make it open source. I took the liberty to assume that the GPL was applied to this plugin as well and began reading the code.

The main plugin-file did not do much, except include a helper-file and call a function within this helper-file. So I opened up the helper-file to discover that it did not contain readable code but something encrypted instead. Looking at the GPL it is absolutely legal to decrypt this encrypted code, so I started decoding it.

BFkWUEZsfUtbXj9YS1gqIC47dzdzUBpQLQlaBQ9KUxgPA1g4XBZdGxwHUzZXVBYyFl1LZ
wkRSRlHDgddQx8KHQEODRUNGA4dXwRXBgBDGR9jF10UcgATSRxaVR1HS11BAVphQh0Wa2
lfFhgKHzxEAB0cTw0aBgMKFg1vHxYLHxcSRlxHTgBUEAJjQhocGgA7BFQCR1IKRwAH


Decrypting the base64 file

The file was encoded with base64 encryption, and any PHP-programmer should know that there is a PHP-function "base64_decode()" to help you with this. The difficult part was that after base64-decryption I ended up with again a base64 encryption. So again I decrypted it, but now I ended up with a base64-encryption locked with a specific encoding key.

$codelock_decrypter["t"] = base64_decode("LlJpagxUIiZLXmc3Ijk5PzUaMCM
pKStbKikEHm48W0FZISlwKSQiVz8jLidnTz8jXxdqGExfWTExNTg+NF4MdzstNRRtHUFe
LSJWTl0NYSYrOWY ...
...
$codelock_decrypter["z"] = substr($codelock_decrypter["license"], $codelock_decrypter["x"] % strlen($codelock_decrypter["license"]), 1);


This CodeLock-encryption is however not impossible to crack. Still this is not real closed source like ionCube or Zend Encryptor - it just takes some good knowledge of PHP to turn the base64-encryption into regular PHP-code. After 15 minutes of good hacking I succeeded in breaking the full encryption and store the PHP-code as a readable content.

There I found the root of the whole problem: The PHP-scripts themselves did not contain any logic by themselves. Instead the PHP-script was encrypted with CodeLock but still able to decrypt itself. After this a request was made to the remote site to get again encryted text which was then decrypted and then executed as PHP. And what was all the fuzz about? About 400 lines of code that I could write easily in one evening.
So what's bad about this Joomla! plugin

Though the functionality of the plugin was very useful, the downtime of the remote site brought a very weak architecture into the light. This is the list:

* The plugin is not clear on the license needed to redistribute the PHP-code. I assumed the code to be GPL, which is probably legally the right assumption.
* The plugin called a helper-file even when the plugin was disabled, which shows that the manufacturor did not actually test things properly.
* The code is encrypted with encryption software written in a manner, which I have seen only with script-kiddies. It contained PHP Notices and even PHP Warnings which were manually oppressed, which is a bad habit.
* The whole functionality depends fully on a remote site. If this site is down, the plugin doesn't work.
* They ask money for this type of software.


How could you know?

You don't, unless you are an experienced PHP-programmer like me. It takes a lot of knowledge to find out what an extension is doing exactly and things get even more complicated with things like base64-encryption. But you can now for sure that with closed source less people are making sure that the PHP-code is of a high quality.


You can find the original post here : http://blog.opensourcenetwork.eu/blog/programming/reverse-engineering-an-qencryptedq-joomla-plugin

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.