Checking for Outdated Joomla Extensions on your server

When you're managing Joomla sites it's reasonably easy to keep track of updates, especially if you use something like Watchful to help you. When you're running a server and only managing some (or none) of those sites, it becomes a little more difficult (especially on a busy shared hosting server).

It's quite easy to shrug and say 'Not my site, not my problem', but the simple fact is that it is. The second someone manages to compromise one of the sites you host, they're going to try and find a way to run arbitrary code, once they've done that they'll try to run an auto-rooter. If they succeed, it's game over for everyone you host!

The extension that always comes to mind, is the Joomla Content Editor (JCE) as they had a nasty vulnerability involving spoofed GIFs some time back. You'd hope that everyone would have updated by now, but there still seem to be a lot of sites running versions older than 2.1.1!

In this post, we'll be creating a script designed to automatically check every one of the sites you host for a version of JCE older than the latest. Adjusting it to check other extensions is easy, so long as that extension has an update stream.

 

Update Streams

The example below gives the correct update stream for JCE, but it's worth knowing how to find the URL so that you can adapt for other extensions. 

If you download a copy of the extension you want to check, within the ZIP will be an XML manifest file (with the same name as the extension). Somewhere in there, will be (if the extension has one) a section like this, where SOMEURL and SOMENAME are whatever's relevant to the extension.

<updateservers>
<server type="extension" priority="1" name="$SOMENAME"><![CDATA[$SOMEURL]]></s$
</updateservers>

It's SOMEURL we're interested in, but also make a note of the manifest filename.

 

The Script

 Basically, what we want to do is search for manifest files for the extension and then check the version from there. There's no point in relying on our remembering to update the script's setting for the latest version manually, so we use the update stream to check.

#!/bin/bash
#
# Check for out-of-date installs of a specific Joomla! extension
#
# Copyright (C) 2013 B Tasker
# Released under GNU GPL V2
# See http://www.gnu.org/licenses/gpl-2.0.html
#

# Set your variables here

# The Update stream, you can grab this from the install manifest
STREAM="https://www.joomlacontenteditor.net/index.php?option=com_updates&view=update&format=xml&id=1"

# The filename of the manifest file used
MANIFEST="jce.xml"
# The directory containing all your hosting accounts
WEBDIR="/home"

# The extension name you want to display
EXT="JCE"


# Processing starts
cd /tmp
# Get the current version from the update stream
CURRENT=$( wget -O - "$STREAM" | grep "<version>" -m 1 )

# Find all relevant manifests
find "$WEBDIR" -name "$MANIFEST" > exts.log

# The manifest will generally be in the back-end
#
# We want to ignore any in tmp as they may be old installs 
# (should be cleared really, but they have no bearing on what we're checking)
#
cat exts.log | grep -v "tmp" | grep "administrator" > exts2.log

# Output the header
echo -n "Out of date $EXT Installs in ( Current version is"
echo $CURRENT | sed 's/[</?version>]/''/g'
echo ""

while read -r a
do
# Output the version
cat $a | grep "$CURRENT" > /dev/null

if [ "$?" == "1" ]
then
# Version string doesn't match the latest version. Out of date (or maybe bleeding edge)!
echo -n $a
cat $a | grep "<version>" | sed 's/[</?version>]/''/g'
fi
done < exts2.log

# Tidy up
rm -f exts.log exts2.log

echo ""
echo "Checks finished"

Adjusting to check a different extension is simply a case of changing the variables at the top of the script, so to check K2 (for example) we'd change to

STREAM="http://getk2.org/update.xml"
MANIFEST="k2.xml"
WEBDIR="/home"
EXT="K2"

The EXT variable simply controls how the name is displayed in the output, so you can set this to whatever you want. WEBDIR is currently set for a CPanel server, so you might want to change to /var/www/vhosts for Plesk, or whichever suits your server. Those feeling really confident could write a script to pull all webroots in from the HTTP server's config, something you might need to do if you've got publicly accessible folders scattered all over your filesystem (Why?)

 

Automating the check

Finally we want to automate the check, so if we save the script above as /root/why_dont_people_update.sh and then chmod o+x it, we just need to create an entry in the crontab (you only want to choose one of the options below!).

# Once a day at 2am
0 2 * * *  php /root/why_dont_people_update.sh

# Once a week - Sunday 2 AM
0 2 * * 6 /root/why_dont_people_update.sh

# Once a month - 1st 2AM
0 2 1 * * /root/why_dont_people_update.sh

The output will end up whereever your cron daemon normally puts it - if you don't receive cron logs by email you'll probably want to change the crontab entry slightly

# Once a day at 2am
0 2 * * *  php /root/why_dont_people_update.sh | mail -s "Out of date" you@example.com

# Once a week - Sunday 2 AM
0 2 * * 6 /root/why_dont_people_update.sh | mail -s "Out of date" you@example.com

# Once a month - 1st 2AM
0 2 1 * * /root/why_dont_people_update.sh | mail -s "Out of date" you@example.com

Now we'll receive a (daily|monthly|weekly) email listing all sites with an out of date install of JCE

 

Improvements

It's not particularly effective, or convenient to need a seperate script for each extension, let alone to have to do the legwork of finding the update stream etc. I did toy with checking every database on the server for the table #__update_sites so that the details could be grabbed from there, but it means not being able to check Joomla! 1.5 sites so easily.

What'd be awesome is if the Vulnerable Extensions List (VEL) had either an API or just a plain XML feed so you could grab a list of known vulnerable and check for those (and earlier) versions.

Still, basic as it is, this script beats the hell out of trying to check every site on a server manually and is definitely a wiser option than turning a blind eye to it and hoping none of your customers manage to get your server rooted!