Hardening the Joomla hacks


I’m wrapping up the Joomla work here so it’s time to talk a bit about security. There are two main issues, sanitizing GET and POST and making sure people who are not supposed to call certain methods can’t do so.

Let’s begin with our constructor which now looks like this:

function __construct(){
	$this->admin_stuff = array(
		'updateTaggedUsers',
		'getUserListByPartial',
		'saveTagText'
	);
	
	$this->frontend_stuff = array(
		'fetchTaggedUsers'
	);
	
	$this->host = 'http://'.$_SERVER['HTTP_HOST'].'/';
	$this->getArr = filterStuff($_GET);
	$this->postArr = filterStuff($_POST);
	$this->baseDir = 'templates' . DS . 'rhuk_milkyway' . DS;
	$this->baseUrl = $this->host.$this->baseDir; 
	$this->tplDir = $this->baseDir . 'html' . DS;
	$this->vars = array();
}

We’re having two access lists, stuff the admin can do and stuff that can be done from the front-end, ie by any user. Anyone who is not logged in won’t be able to do anything. All methods not listed in any of these two arrays are inaccessible by Ajax calls.

As far as the sanitizing goes we’re using filterStuff():

function filterStuff($arr){
	foreach($arr as $key => $val)
		$arr[$key] = mysql_real_escape_string( filter_var($val, FILTER_SANITIZE_STRING) );
	return $arr;
}

We’re using both filter_var and mysql_real_escape_string and it seems to be working so far, I haven’t noticed any screwing up of data so far from this arrangement. So instead of using the $_GET and $_POST variables directly we will now exclusively use getArr and postArr, Joomla might be doing its own things with these two global arrays so we don’t want to mess with them directly for fear of double escaping and stuff like that.

Given the above the cExt function now looks like this:

function cExt($func = ''){
	$cext = null;
	if(!empty($GLOBALS['cExt']))
		$cext = $GLOBALS['cExt'];
	else{
		$GLOBALS['cExt'] = new plgCommunityExt();
		$cext = $GLOBALS['cExt'];
	}
	if(empty($func))
		return $cext;
	else{
		if(!in_array($func, $cext->admin_stuff)){
			if(!in_array($func, $cext->frontend_stuff)){
				echo "no access";
   				exit;	
			}
		}else{
			$user = & JFactory::getUser();
   			if(!in_array($user->usertype, array('Super Administrator', 'Administrator', 'Manager'))){
   				echo "no access";
   				exit;
   			}
		}
		
		if($GLOBALS['ajax'] == true)
			$cext->$func();
		else
			return $cext->$func();
	}
}

As you can see we haven’t yet made any provisions for the case when we will only allow logged in users in the front end to call something. The reason for this is that the fetchTaggedUsers method is supposed to work for people not logged in too.

Related Posts

Tags: , , ,