Disabling PHP on a per-directory basis

Any PHP web application that allows uploads, by necessity, is going to need to vary permissions on a per-directory basis (unless you want to just save a hacker some work and make the directories that contain code files writeable by the webserver). Magento needs to be able to write to ./var, ./media, and also ./app/etc if you want to run the installer.

The ./media/ directory is an exceptionally temping gap in the application’s armor, because files there are also web-accessible out of necessity. That means if an attacker can manage to write a code file there, they can then execute it at will by simply requesting the file in a browser or sending an http request another way.

One of the easiest and most effective countermeasures against this method of attack is to simply block php execution in directories that should not contain php files. While it’s tempting to use an .htaccess file (.htaccess files in themselves kind of suck for both security and performance but that’s a diatribe for another day), there is a high risk of an attacker just overwriting it with a new, looser .htaccess file.

Instead, use the following in your Apache virtual host file (test these first, they’re tweaked snippets I found online but they look about right)

<Directory /media>
    <FilesMatch "(?i)\.(php|phtml)$">
        Order Deny,Allow
        Deny from All

… or your nginx config file

location ~* /media/.*\.(php|phtml)$ {
    return 404;

That should block any files with .php or .phtml file extensions in the directory from being parsed. You might want to do the same for ./var/, depending on the installation – the preferable action is to hide ./var/ from the web completely, but some installs with import/export extensions and other 3rd party code require allowing some access.

Debugging Magento Routing

Magento’s choice of configuration (via XML) over convention is part of what makes the system so awesomely flexible and extensible. The downside is that it also has a tendency to lead to those ‘WTF’ moments when you know you’ve done *something* wrong, but you have no idea *what*.

Having some background on Magento’s routing system is super helpful in the situation where you’ve created a controller and a route, but for some reason your controller is not being used and you’re getting an unhelpful 404 page instead of whatever functionality you’re expecting. The meat of the code that handles request routing in Magento can be found at ./app/code/core/Mage/Core/Controller/Varien/Router/


In the case above, it can be useful to refer to the standard router in Standard.php, specifically the match() method. This contains the bulk of the logic that tries to match a URL to a module, controller, and action. You can dump or inspect the contents of $this->_modules, or just the local $modules, to view the modules Magento has registered, and $p to see how Magento has broken the URL parts up.


It can also be helpful to dump and do a search on the global config object – I wrote a super simple free extension to do just that.


semanage: command not found

SELinux is a great tool for enhancing webserver security (that I’ve written multiple posts on), but if you ever get this message, you need to install the policy utils.

yum install policycoreutils-python

… should install the the semanage tool and all dependencies. Shooting from the hip but it’s probably apt-get install policycoreutils-python on Debian/Ubuntu.