Input Sanitization using JRequst

Authors:
  • Eric Goldman

29 May 2009   ::   Web Development   ::   #Joomla #sanitization #input #GET #POST

 

Think about the most basic kind of web page you can create, static HTML. In this sense, you are not expecting any input (either from the user or via a link) to effect the output. This was the easy life back in the early days of the Internet, and life was good. Today, most websites are dynamic. This is most likely why you are using a CMS like Joomla. Now, you may not include any “interactive” features on your website, but the second you start using Joomla your site truly is interactive, because a dynamic site relies upon dynamic content. In most cases, you may (think that you) control the input, but there is really nothing stopping the user from changing the dynamic instructions you set.

Let’s take simple example. You have a muli-page article. On the bottom of page one you have a link with a target like this somesite.com/index.php?page=2. At first glance, this looks innocent enough. But there is nothing stopping the user to changing that value and submitting it to your website. But what’s the worst that can happen? They change page=2 to page=3 and they go to page 3.

That’s one possibility, but if you do not filter and validate your input, they may be able to inject arbitrary code and get your application to do something funny.

This may seem fairly obvious in today’s world of XSS, CSRF, and other nasty acronyms. However, if you are writing Joomla components you must take this into account. As Joomla grows in popularity, hackers will be drawn to attack your code. Further compounding this issue is that most Joomla site owners know absolutely nothing about HTML never mind web security or procedures. That is why you must make your code as strict is possible - I know this if often very hard in a loose language such as PHP on which Joomla is built.

But alas, Joomla provides a great class that does a lot of the dirty work for you, JRequest:

JRequest Class Description: This class serves to provide the Joomla Framework with a common interface to access request variables. This includes $_POST, $_GET, and naturally $_REQUEST. Variables can be passed through an input filter to avoid injection or returned raw.

The first thing we should look at here is the getVar method. Here is the method prototype:

mixed   getVar  (string $name, [string $default = null],
 [string $hash = 'default'], [string $type = 'none'], 
 int $mask)

So let’s dissect this little beast. The first thing you specify is the variable name, this would be the key from the request hash. For example, if you wanted to get the value for $_POST['foo'] you would call `getVar(‘foo’).

The rest of the parameters are optional, but these are the things that will help protect your code from unexpected input and thus undesired output. The second parameter is a default value that will be used should the variable requested not be set. This is a good idea as your input-processing is expecting a value anyway, and it saves you the time of writing something more complex like this:

$foo = $_POST['bar'];
  if( !is_set($foo) ){
  $foo = 'default';
}

Saving keystrokes is always nice, especially considering my typo-prone digits. The next variable is the $hash which would be one of the associative arrays such as $_POST or $_GET. You should ALWAYS set the hash you want. Why? First, you should always know exactly where you’re input is coming from and second, it defaults to $_REQUST, which means that the input your are expecting may come from a different hash that an attacker was able to modify through some other exploit (See this article by Sam Young). Even if you think the further security mechanisms down the processing chain could take care of this occurrence, there is really no reason not to specify the input hash. I would also recommend avoiding using the ‘method’ hash option, unless you know what you are doing.

The next parameter is the type. This is the datatype primitive that you are expecting and can be any of the following:

INT, FLOAT, BOOLEAN, WORD, ALNUM, CMD, BASE64, STRING, ARRAY, PATH, NONE

Most of those should seem familiar to you. ALNUM is a type defined as an alphanumeric string with the following regex '/[^A-Z_]/i', CMD is defined as '/[^A-Z0-9_\.-]/i', WORD as '/[^A-Z_]/i', and PATH is a more complex regex for a directory path. CMD is just a locked down string that should be url-safe and if often used when getting GET parameters (command inputs for a task/controller). In most cases, you should know which type you want to use. The variable will be cast to the type you select (If you are expecting a number, make sure the input is a number!). You should avoid using the plain string type whenever possible. One of the other specialized text types with usually be much safer. To get a better understanding look under the hood.

The last parameter $mask defines a bit filter to be used. Joomla has four predefined filters which will help further sanitize your text strings. Here is how they are defined in Joomla:

Filter bit mask:

1=no trim: If this flag is cleared and the input is a string, the string will have leading and trailing whitespace trimmed.

2=allow_raw: If set, no more filtering is performed, higher bits are ignored.

4=allow_html: HTML is allowed, but passed through a safe HTML filter first. If set, no more filtering is performed.

If no bits other than the 1 bit is set, a strict filter is applied.

A bit filter means you can specify multiple options at once via the magic of binary math. To see the processing, check the API.

Now, to add readability to your code, you can also use some proxy methods which will set the type for you, these include getInt, getCmd, getString, etc. You can always use getVar, but using the proxy methods is probably a good idea when possible.

Note that all of the accessors (the functions that start with “get”) in JRequest are static, which means you can call them without creating an instance of the JRequest class.

In JRequest there is also one other method which is interesting when considering input sanitization, the clean() method. This method does some sanitization on all the GLOBAL hashes, it makes sense to run it before doing further processing.

Examples

Given the following variable set:

$_GET['foo1'] = 'bar1';
$_GET['foo2'] = 'bar2';
$_GET['foo4'] = 'bar4 ';
$_POST['foo1'] = 'rab1';
$_POST['foo2'] = 'rab2';
$_POST['foo3'] = 'rab3';

Here is how the filtering would work:

$o1 = getVar('foo1', 'default', 'GET', 'CMD'); 
echo "\'$o1\'"; //output: 'bar1'

$o2 = getVar('foo3', 'default', 'GET', 'ALNUM'); 
echo "\'$o2\'"; //output: 'default' 

$o3 = getVar('foo1', '1', 'POST', 'INT'); 
echo "\'$o3\'"; //output: '0'

$o4 = getVar('foo4', 'default', 'GET', 'STRING'); 
echo "\'$o4\'"; //output: 'bar 4'

$o5 = getVar('foo4', 'default', 'GET', 'STRING', '1'); 
echo "\'$o5\'"; //notice the addition of a filter mask,
                //output: 'bar 4 '

$o6 = getCmd('foo2', 'default', 'POST'); 
echo "\'$o6\'"; //use proxy function, output: 'rab2'

*Note both hash and type will be converted to uppercase for you in their processing.

So by using JRequest you are on your way to securing your Joomla extensions from all sorts of nasty injections. If an when additional security flaws are found, it is likely that the Joomla team will fortify the code here, providing a single piece of code that needs to be fixed. By using JRequest you may lock yourself into Joomla-specific functionality, but it provides some forward-leaning code protection.

Good day, and good (secure) coding.