How to Prevent SQL Injection in Joomla

SQL Injection is the most dangerous hacking techniques out there. With SQL injection, a malicious attack can drop you a table or even a whole database in a few seconds and with a very simply command through your website. In this day and age, it is unacceptable for any website to have a SQL injection vulnerability, since security experts have been warning about SQL injection for at least a decade now – and, addressing SQL injection is a well known and well documented process.

How does SQL injection happen?

Let’s say you have the following page on your website: http://www.yourjooomlawebsite.com?userid=5. This page displays the information about the user on your website with an id = 5. Somewhere in the page displaying your website, you have this code:


$user_id = $_GET['user_id'];
$db =& JFactory::getDBO();
$db =& JFactory::getDBO();
$sql = "SELECT * FROM jos_users WHERE user_id='".$user_id."'";
$user_information = $db->Execute();

Now, when the id is 5, then the query above will be:

SELECT * FROM jos_users WHERE user_id='5'

The above is OK, and it’ll work. But an unscrupulous visitor might change your URL to the following: http://www.yourjooomlawebsite.com?userid=5′; TRUNCATE TABLE jos_users–

Here’s what will happen in the above case:

  • The query will become SELECT * FROM jos_users WHERE user_id='5'; TRUNCATE TABLE jos_users--' – which means that instead of having one query, we have now two queries.
  • The first query is executed, and the information about the user with id equals to 5 is stored in the memory.
  • The second query, TRUNCATE TABLE jos_users is executed. This query will delete your users table!
  • The -- is the comment syntax in MySQL, and thus everything after it will be ignored. This means that the apostrophe will be considered as a comment and will be silently ignored. This prevents MySQL from generating an error because of the apostrophe and ensures that the malicious SQL query will run smoothly.

Now, of course, the above URL can do far more damage if it’s something like http://www.yourjooomlawebsite.com?userid=5′; DROP DATABASE yourjoomladatabasename–. This URL will delete your whole database!

I think after reading the above it’s easy to realize how much damage can someone do to your website with very little effort!

Where does SQL Injection happen?

The core Joomla installation of any of the recent versions: 1.5.25 and 2.5.1 doesn’t have any SQL injection problem (some versions prior to these versions may have SQL injection problems) – so if you install the latest version of Joomla on your website and only use the official extensions, you’re safe. However, once you start installing 3rd party extensions (which is usually the case for any Joomla website administrator), then you might start running into security issues. The thing is, the Joomla engine tries its best to secure the bad code in 3rd party extensions – however, it’s not always successful at this task, especially if the code is really, really bad like the code above.

How can you protect your Joomla website from SQL injection?

There are several things that you should do in order to protect your Joomla website from SQL injection – these things must be done at the MySQL level, the PHP engine level, and the code level:

  1. Things to be done at the MySQL level to prevent SQL injection:
    • Disable comments. This alone will prevent the above malicious SQL from running as its syntax becomes wrong (because of the quote).

    • Do not give DROP and TRUNCATE permissions to the Joomla MySQL user. This is a good practice but may cause problems for you when you uninstall an extension that creates its own tables (the uninstall process of the extension will not deal the associated tables).
  2. Things to be done at the PHP engine level to prevent SQL injection:

    There is only one thing to be done at the PHP engine level to prevent SQL injection, and it is to make sure that the flag magic_quotes is set to “on” in your php.ini file. Magic quotes escape user input automatically by adding slashes to quotes. Note that as of PHP 5.4.0, this flag has been deprecated which means that a lot of previously thought secure code running under earlier versions of PHP will no longer be secure under new versions of PHP.

  3. Things to be done at the code level to prevent SQL injection:

    • Never, ever trust user input. Always work with the mindset that user input is bad.
    • Use the Joomla static function JRequest::getVar($variable_name, $default_value, $value_type, $mask); instead of accessing request variables directly through $_GET and $_POST. For example, if you want to access the above variable, you write the following code:

      $user_id= JRequest::getVar($user_id, 0, '', 'INT');

      By using this function to access request variables, you will ensure that all user data is filtered before it’s used somewhere else (such as in SQL queries).

    • Use eval functions very, very carefully – especially when you’re evaluating user input.

    • Strip the words eval and call_user_func from user input. This is an added security measure in case you have a security hole in your code that you are not aware of.

Doing the above will ensure that your visitors are not able to break your Joomla website by injecting malicious SQL into your code. We also suggest that you read these security tips to enhance the security of your Joomla website.

If you don’t have the technical skills to do the above, then worry not. We’re here to help. Just contact us and we’ll ensure that your website becomes safe from SQL injection. By the way, our fees are very reasonable!

10 Responses to “How to Prevent SQL Injection in Joomla”
  1. Comment by Mat — July 18, 2012 @ 9:36 pm

    How does $user_id= JRequest::getVar($user_id); actually prevent the SQL injection?

  2. Comment by Fadi — July 19, 2012 @ 2:11 am

    Hi Mat,

    getVar method on the JRequest class automatically filters out the input (unless explicitly told otherwise). Please refer to the getVar documentation on the Joomla website.

  3. Comment by Rogerio Brito — April 28, 2013 @ 3:49 pm

    Using only $user_id= JRequest::getVar($user_id); does not protect against sql injection.
    I just tested one of my sites using sqlmap and it was able to get a lot of info from my database.

    To protect the site I had to change that code to:

    $user_id= JRequest::getVar($user_id,”,’INT’);

    That forces the $user_id to be an integer, and so not injectable.

  4. Comment by Rogerio Brito — April 28, 2013 @ 3:59 pm

    I´m sorry, the above code is missing an argument.

    For a GET the code should be:

    $user_id= JRequest::getVar($user_id,’’,’get’,’INT’);

    And for post:

    $user_id= JRequest::getVar($user_id,’’,’post’,’INT’);

  5. Comment by Fadi — May 21, 2013 @ 4:48 am

    Hi Rogerio,

    You’re right – the code above is fixed. The reason for the error is that the function getVar invokes the function _cleanVar (on the same class) which ultimately invokes the function _cleanTags on the JFilterInput class. The assumption was that somewhere the cleanup must happen – but all these functions were basically doing nothing if no mask was given (the mask is the second parameter).

  6. Comment by Drew — January 9, 2014 @ 10:24 am

    I am trying to research and ensure that there is no vulnerability in using “JRequest::getString” type coding. We are looking to utilize this within an affiliate tracking type code for one of our merchants, but I’m not finding anything within Google Searching at the moment on if this is a liability. Much appreciate any assistance.

    Drew

  7. Comment by Fadi — January 9, 2014 @ 10:28 am

    Hi Drew,

    What is the format of the that tracking code?

  8. Comment by Drew — January 9, 2014 @ 10:39 am

    It’s an image and the src of the image sends/alerts the information to the external affiliate program. The src needs to contain the order amount and the order number along with the merchant number to assign it to.

    This is for a joomla 2.5.16 and virtuemart 2.0.24 site; the final checkout page we found has most of the variables within the url itself so we are using the getString to grab those values and place them within the img src code.

    is that what you were looking for?

  9. Comment by Duncan — November 17, 2014 @ 8:13 am

    Hi,

    I have a couple of 1.5 sites that keep getting attacked, I have plans to upgrade to 3.4 when it comes out, but it’s been a long wait.

    In the meantime you say to use the function JRequest::getVar($variable_name, $default_value, $value_type, $mask);

    I’m really not very good with coding, could you describe where I put this code, i.e. which document. Is it the root index.php file?

  10. Comment by Fadi — November 18, 2014 @ 5:11 pm

    Hi Duncan,

    Is your database hacked or is it the filesystem? If it’s the database, then I suggest you try removing all the 3rd party extensions that are deemed to be vulnerable. If it’s a filesystem hack, then I suggest you check this post: http://www.itoctopus.com/why-you-should-use-dso-for-joomla-websites

    Either way, you will need to migrate to Joomla 3.x as soon as possible.

Leave a comment