Security Tip: Prevent Fake Image Upload Hacks from Working

How to modify your .htaccess file to provide better security against a too-common vector of hacking a Joomla website.

This little kitty uploaded a PHP file via an image-upload form. If you're lucky, that's all he did before his nap.As I've harped many times recently across the Internet, Joomla's /images/ folder is widely targeted as a vector of site hacks. The cause: extensions which enable image uploads without proper security - especially those which lack the bare-minimum of what coders call a "sanity check" - such as the question of whether the files being uploaded are, in fact, even actually images.

The nugget of this article is a snippet of code for your .htaccess file. Something functionally identical to it may be added to Joomla in the very near future -- but if you install a Joomla site before then, you won't get the added security, because of reasons discussed herein.

In this article, I'll show you how to add a snippet to your .htaccess file, which does not close this security gap, but does limit or kill the effectiveness of exploiting it. It's time for another verbose attempt to bring an advanced topic to a basic level of understanding, in hopes more people will benefit...

Warning: Back-up your .htaccess file before working, and after every successful step, whenever working with it!

Perhaps the best feature of this solution is that, if you're already in the early stages of having been hacked, but the hacker has been busy. you may prevent further progress! (This actually happens fairly often - they score automated intrusions against many sites, but don't immediately do anything with the access.) This is because we will prevent PHP files from being run in the /images/ folder, and hackers often upload an installer script via image-uploader forms, then run it later to gain more control. It is the running of PHP files in /images/ we will block with this solution.

Would you like me to apply this security fix to your site? Contact me!

I'm Sorry, You Must Read This

We'll do this by adding URL Rewriting rules to a special configuration file. This file isn't technically part of Joomla, but may have been provided by it. There's an important warning ahead, but first, some critical education, in order to make sure you understand the weight of the caution.

What is .htaccess

Joomla ships with the file htaccess.txt, which is intended as a basis for the file .htaccess. The file .htaccess lets you set options for your site at a high level of control above and beyond both Joomla and PHP. This is because it lets you configure how the web server software itself treats your site -- or, rather, the parts of your site descending from the folder where .htaccess is found. (Note, some hosts specifically don't fall-back to parent folders seeking a configuration file; see "If That Didn't Work," below.)

Since it hasn't been said explicitly yet, let me be perfectly clear about how to activate this configuration file: A file named htaccess.txt, is not active -- it's just a text file. Renaming or copying htaccess.txt to .htaccess, will activate its features. To make further changes, as I'll suggest below, you edit .htaccess.

That's still not the actual caution -- it's coming, and it's important.

Why Joomla Ships htaccess.txt Instead of .htaccess

Most new sites don't start with an .htaccess file. This is because you might have one already, or might plan to copy one, such as htaccess.txt, distributed with some web app. The content of htaccess.txt is necessary for Joomla's SEF URLs with URL Rewriting, and also contains a few security features similar to the one I'm about to show you - so, whether or not you want to use URL Rewriting specifically for SEF URLs via that Joomla feature, you can still use htaccess.txt as the basis of your site's .htaccess file.

So now, the caution: You may already have an .htaccess file and your web host may be hiding it from you. The web-based File Manager app in your hosting control panel, may hide "dot-files" -- files whose names start with a dot -- and, worse, might not warn you if you're about to overwrite it! Therefore, it's a good idea to use a desktop-based FTP program such as Filezilla, if you have "pretty URLs" but can't find .htaccess. Another option is to use Akeeba Backup to take a full, Zip-style backup -- it will contain your .htaccess file if your site has one. You could then modify that file and upload it to your site; but, guess what! Some hosts whose File Manager apps hide .htaccess, also won't allow you to replace it, but will report a successful upload! So, again, you may be stuck learning to use Filezilla or another FTP app.

This quagmire of instructional caveats is the reason why existing sites won't get these security advantages if they were installed before Joomla incorporates them - there's no easy way to help every person get a patch into their .htaccess file -- not without risking breaking a file that is commonly hand-edited to custom, mission-critical effect.

Final Caveats

It's worth noting in bold that you don't> need to enable SEF URLs or URL Rewriting in Joomla's Global Configuration, in order to use this technique -- but you do need to use an .htaccess file (note there's a dot at the front of that filename), as is also required for that URL option.

Owners of brand new sites using only Joomla (and not any other web apps, nor other heavy customization) probably could have skipped reading all of the above. I'm sorry for how complicated web technology is. I really am.

Getting To It

The pros and cons of this approach:

Pros:

  • Existing, incomplete hacks are neutralized
  • Future hacks targeting uploads to /images/ are neutralized
  • Only blocks actual PHP files in /images/; won't collide with Joomla content
  • No performance footprint; uses a plain 403 Forbidden response

Cons:

  • Requires your server to support URL Rewriting (aka mod_rewrite among web server geeks)
  • Only protects the /images/ folder, and only from web-based attack
  • Only covers Apache versions 2.2 and 2.4 (may work in 1.3 but not tested for that version)

This solution is for Apache-based web servers, which means nearly-all Linux servers, and many others. (Apache is the web server software; alternatives include IIS and Nginx, which each have different configuration styles and are, sadly, not covered by this article.)

Where to Put the Code

If, for whatever reason, you don't want to use the default htaccess.txt as the basis of your .htaccess file, then I can't give precise directions; you need to have this line somewhere in your .htaccess:

RewriteEngine On

That portion needs to come before this portion:

# Custom security: no PHP scripts in /images/
RewriteCond %{REQUEST_URI} ^/images/.*(\.php|\.php3|\.php4|\.php5|\.phtml)$ [NC]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -f
RewriteRule .* index.php [F]

If that fails, put the following line immediately after RewriteEngine On:

RewriteBase /

Note: If your site sits in a subfolder, modify that; for example:

RewriteBase /joomla/

Be sure to include both slashes, at the beginning and end, as well as any between (for nested subfolder structures).

Now, if you do use Joomla's htaccess.txt as the basis for your .htaccess file, it's more certain where you make the change. Look for this block:

## Begin - Custom redirects
#
# If you need to redirect some pages, or set a canonical non-www to
# www redirect (or vice versa), place that code here. Ensure those
# redirects use the correct RewriteRule syntax and the [R=301,L] flags.
## End - Custom redirects

Place it amid those comments (every line in this file beginning with the # sign, is called a comment; it's either a note, or a piece of code that's been disabled). Assuming your custom redirects section was blank to begin with, you'd end up with this:

## Begin - Custom redirects
#
# If you need to redirect some pages, or set a canonical non-www to
# www redirect (or vice versa), place that code here. Ensure those
# redirects use the correct RewriteRule syntax and the [R=301,L] flags.

# Custom security: no PHP scripts in /images/
RewriteCond %{REQUEST_URI} ^/images/.*(\.php|\.php3|\.php4|\.php5|\.phtml)$ [NC]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -f
RewriteRule .* index.php [F]

## End - Custom redirects

To Test

A simple test: put the following code into a file called test.php and upload it to your website's /images/ folder. (Note: The .txt suffix may be added by Notepad and hidden by Windows - catch that when you upload!)

<?php

echo 'Drat, PHP files still run in the /images/ folder!';

?>

After you've uploaded that, you test by trying to hit that script in your web browser. If your Joomla homepage was www.nathanhawks.us then you'd hit www.nathanhawks.us/images/test.php. If you hit that URL during various stages of this process, here are the results to expect:

  • Before doing anything: It will display a Page Not Found error, as you have not created test.php yet.
  • After uploading test.php, before changing .htaccess: It will display "Drat, PHP files still run in the /images/ folder!" on a plain white page.
  • After changing .htaccess, before uploading test.php: It will display a Page Not Found error.
  • After doing both steps: It will display a plain Forbidden error.

If you get a Forbidden error hitting test.php on your website, you're done! Any facility on your website which uploads files exclusively to the /images/ folder are no longer a threat for execution of user-uploaded scripts. That mouthful means people can't use image uploader forms to hack your site anymore.

Remember, if a hack has already been fully carried out on your site such that the hacker has gained greater access, this method does not fix that.

If That Doesn't Work

First, if your server doesn't support URL Rewriting, you might get an Internal Server Error. If that happens, just undo the changes you made to .htaccess.

An alternative reason this might not work is due to the way some servers refuse to perform fall-back functions with respect to .htaccess. You might have to copy-paste the .htaccess file into the subfolders of your /images/ folder, to get protection on a few sites. If the above test gave expected results, you're already set, and don't need extra copies of .htaccess.

Rare Apache hosts don't allow any configuration via .htaccess whatsoever. Were I a customer of such a host, I'd be gone faster than I could say "my mistake." (Honestly, I'd do the same with a host that didn't support URL Rewriting, too, as these are basic necessities.)

Final Notes

None of this is a substitute for more-comprehensive security practices. In particular:

  • Don't allow any extensions to add image-upload capability to the front-end unless you're ready to monitor the Vulnerable Extensions List, and perform updates if a version of the extension appears on the VEL.
  • Have a programmer review image-upload extensions you do use, to check for malicious or sloppy code - particularly, have them ensure PHP and JavaScript files can't be uploaded as if they were images.
  • Use correct file and folder permissions and never set permissions ending in -7 or -6 on any file or folder!
  • Keep Joomla and all other extensions up-to-date with security patches for your series. (I offer a service to update Joomla as soon as security updates are released)
Would you like me to apply this security fix to your site? Contact me!