Hardening the Joomla hacks
Table of Contents for Paceville.com - The Coding
- Customizing Joomla 1.5
- Adding AJAX to Joomla 1.5 with jQuery
- Adding custom columns/fields to Joomla article, section and user
- Hardening the Joomla hacks
- Hijacking controllers and views in Joomla
- Search Engine Friendly urls in Joomla
- Facebook style information box with jQuery
- Image manipulation and watermarking in PHP with GD2
- Joomla! 1.5x Customization – Book review and general Joomla discussion
- Mailing with Joomla’s JMail
- Lost Flirts – a Joomla 1.5 component from scratch
- Facebook style photo tagging with jQuery, Ajax and Joomla
- Controlling form tabbing with jQuery
- Facebook style chat with jQuery and Joomla
- JQuery Joomla chat, adding online/offline and friendlist
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.