Securing ExpressionEngine 2
by Mark Huot
Last month EE Insider asked the readers “What do you rename your system folder to?” The responses ranged from common dictionary words to random strings and everything in between. The responders are obviously concerned about security and doing what they can to ensure malicious users or bots cannot attack their Control Panel. Let’s take a look at a simple way to secure your ExpressionEngine 2 (EE2) installation.
The System Folder
In the root index.php file there’s a line near the top that tells EE2 exactly where to look for the system folder. This is your first line of defense against malicious attacks. Security through obscurity it’s sometimes called but it works surprisingly well.
$system_folder = 'system';
This isn’t iron clad security but it sure is better than an easily guessable /system folder. Now, let’s make it better.
It is not obvious from the variable name or the default value, but the $system_folder variable isn’t just looking for a directory name. It can take an entire server path to your system folder. We’re not limited to just system there, we could write private/system and nest our control panel within an .htaccess protected private directory. We could also go the other way and pull our system folder up a level outside the web root like so:
$system_folder = '../sys';
On a typical Apache install, where your index.php file is located at /var/www/vhosts/example.com/httpdocs/ the preceding system_folder call to ../sys would tell EE to look to /var/www/vhosts/example.com/system/ for system files. This is immesaurably more secure than just renaming your system folder because you’ve moved all your private info outside of the web realm. No longer can attackers guess your system name and navigate right to your system/expressionengine/config/config.php file.
An increasingly common attack is to search for Subversion’s .svn directories within your web root and infer an application’s directory structure from the entries file (this is done by navigating to http://www.example.com/.svn/entries). If these aren’t protected by .htaccess you’re giving attackers a full view into your system folder name, the extensions you have installed and even, potentially your template structure.
Simply by asking Subversion for your directory structure, attackers could find and exploit all those templates you thought no one could see and you didn’t need to put a password on, or all those half baked extensions that may or may not be 100% finished. Moving your system folder out of the web realm protects this and gives attackers (potential) access to only the files you deem web safe.
My Secure Setup
Now that we’ve explored what EE2 can do, let’s look at a typical secure setup. Here are the paths I use for various parts of my EE2 installation:
/var/www/vhosts/example.com/httpdocs/pub
/var/www/vhosts/example.com/httpdocs/sys
/var/www/vhosts/example.com/httpdocs/tpl
/var/www/vhosts/example.com/httpdocs/lib
Let’s take a look at each one individually.
/var/www/vhosts/example.com/httpdocs/pub
I’ve chosen to keep everything inside of the traditional httpdocs directory and rewrite my Apache DOCUMENT_ROOT via a virtual host. In this instance I’ve rewritten it to /var/www/vhosts/example.com/httpdocs/pub. Primarly this helps future developers find everything in the “expected” location of httpdocs. Secondly, there are many backup solutions, including some fairly popular Plesk solutions that only backup the httpdocs directory so keeping everything inside ensures compatability with a wider array of software.
This method also play nice with a shared hosting environment like Dreamhost where your domain would live at ~/example.com/pub/.
/var/www/vhosts/example.com/httpdocs/sys
sys is my renamed system folder to keep my anal retentive tendencies in check and ensure each folder is three characters. This is the path I place in the $system variable in index.php file in EE2.
/var/www/vhosts/example.com/httpdocs/tpl
tpl is simply the templates folder broken out to make it easier to access without drilling down through system subfolders. I can place this in the site’s config.php file to let EE2 know where the templates are located.
/var/www/vhosts/example.com/httpdocs/lib
lib contains any 3rd party scripts in use on the site such as phpThumb or ReCaptcha.
Put all of this together and you have a simple and secure way to run on your EE2 website.
Post to Twitter
Post to Delicious

giuliano — 08:27 on 05.11.2010
Really simple and useful.
Thanks.
Christopher B — 08:28 on 05.11.2010
I too, have been looking into ways to secure an EE2 installation. The method of moving the system folder up one level outside of the public_html I have read about and seems the most secure. However, then how do you/client login to the backend. The is instead of going to example.com/system, where would you go to login to the Control Panel?
For your secure setup, you provided your naming scheme for your directories, and that you move some of the system directories into the main folder, but other than organization, what do you do to actually secure your system? That is I’m assuming httpdocs is the same thing as public_html correct? Thanks in advance!
Ryan Irelan — 08:34 on 05.11.2010
Christopher,
The client will still log in to the Control Panel using example.com/system. Setting that $system_folder variable is what tells EE where to look.
Christopher B — 08:45 on 05.11.2010
Oh I see. So other than being able to login, if you try accessing files directly such as the config (as you mentioned above) you would be unable to, if the system file is outside the public directory? (That makes sense)
But if you can still go to example.com/system, bots can still try to guess username and password correct? Meaning if you move the directory up one, it protects files better, but you would still want to change the directory name to something obscure to prevent the bots from accessing the login page right?
Going to eeinsider.com/sys however returns a page not found so maybe you have found away around this.
Also couldn’t someone simply turn on firebug to see which directory certain files were loading from to determine the name of the system file?
I’m use to Joomla and now WordPress so pardon my ignorance at EE. Though I did just purchase a copy of EE2 and a copy of your book I have just started. So I’ll be caught up soon!
Christopher B — 12:03 on 05.12.2010
After rereading, I now realize that /pub/ is your public directory, so infact sys, tpl, and lib are infact outside (above) the public directory. Makes much more sense now.
Question, in regards to, “I can place this in the site’s config.php file to let EE2 know where the templates are located.”
I looked in the config file and did not see an option for changing the location of the template folder. What code did you add to to do that? Thanks!
Mark Huot — 12:12 on 05.12.2010
@chris it’s not in the default config any more but a little sleuthing in EE and you’ll find you can add:
$config[‘tmpl_file_basepath’] = “.../tpl/”;
Christopher B — 12:13 on 05.12.2010
Awesome thanks Mark!
Ikaika Hussey — 23:05 on 06.01.2010
Does this same approach apply to EE 1.6.x?
Ebola — 23:33 on 06.01.2010
How do you access the system if you have placed it outside of document root? mod_rewrite?
Mark Huot — 02:39 on 06.04.2010
@Ikaika: Absolutely! And it works the same way, change the path in index.php as well as the template path in config.php
@Ebola: The control panel is accessed through the “masked control panel access.” In EE2 this is done by copying the `system/index.php` into the document root and pointing it at the system folder via a configurable path (within the file).
See:
* http://expressionengine.com/docs/installation/masked_cp_access.html
Adam — 11:55 on 06.24.2010
Thanks for this article, very useful- I’m interested in your method of keeping everything inside the traditional httpdocs directory and re-writing your Apache DOCUMENT_ROOT via a virtual host- it seems like a great way to develop a consistent, easily repeated EE installation but I get lost at re-writing the document root- I only took a quick look, but is that done via httpd.conf? Access to Apache configuration doesn’t seem to be typical within shared hosting environments, or at least not the one’s I’m familiar with- could you give a little more insight into that process?
Thanks!
Stuart McCOy — 15:51 on 06.28.2010
I’m with Adam here. I’m trying to develop a way to work on my MacBook Pro locally using virtual hosts to mimic the live site structure as close possible. I’d like to add this level of security and organization but I’d like to see a clearer step-by-step article explaining the process a little more clearly. I’ve got the virtual hosts stiff own, I’m a little stuck on the security, masked CP’s, etc. but putting this into the virtual hosts context would be helpful too.
Christopher B. — 17:18 on 09.22.2010
Good Evening,
I tried this method back when this was published and while ran into difficulties eventually got it working properly. However, then EE 2.1 update came out, and felt lost on how to upgrade the system.
I tried replacing just the files/folders that were new, but then the instructions prompted me to run the database update, but it would not work, since folders where not where it expected them to be (after moving them according to instructions above).
Eventually I had to start fresh.
So my question is, with the secure setup above, what is your exact procedure for updating to new EE releases? Thanks in advance!
Christopher B. — 12:15 on 09.23.2010
Seems there is a new ebook out on the topic that looks like goes into great depths and hopefully provides a proper upgrade solution: http://mijingo.com/ebooklets/securing-expressionengine-2
Adam — 14:24 on 09.27.2010
Christopher, did you find a solution to updates? What I’ve done is temporarily restore a “normal” system folder location within the root, run the updates, then return the configuration/system folder location to outside the root…
Christopher B. — 14:36 on 09.27.2010
Yes, Thank you Adam. That is actually what I attempted to do as well but everything still broke. Hopefully a fluke or forgot some step.
EE has not released an updates since 2.1 so haven’t gotten a chance to try again. When they do I will once again rename my system folder back to “system” rather than its new name, move it into the original location, update the config files to reflex this, move the template folder back to its original location, update the config file to relfect this, change the index file back to its original name and update config to relfect this. Run the database upgrade and then do all the steps above all over again in reverse to resecure the site.
Honestly quite the hassle. As with of course WordPress you simply click “Update” in the admin and in a matter of seconds your system is updated. Even from version 2 to version 3. And this functionality works the same when you move the wordpress system files above the public directory. This is one big place EE needs to play catch up as well as not being able to install addons through the admin. Or a list in the backend of out of date addons (like in Joomla 1.6).
Cross my fingers for EE3!
Adam — 14:36 on 09.27.2010
Agreed- I was actually very surprised when the update didn’t work with the system folder above the root…
Chun Kit Chris Wong — 22:57 on 11.19.2010
Hi Mark,
Today I just purchased your book, “Securing ExpressionEngine 2” and it is a great read. However, I do have a question. In the beginning of the book, you mentioned that it would be a bigger issue “if someone were to access http://www.example.com/system/templates/twitter.php” I am wondering if someone can easily access these files. I did a testing and ee2 would not let me in because this is forbidden. May you further support your practice? I really appreciate your help and insight.
Thanks,
Chris
Mark Huot — 09:55 on 11.20.2010
What wonderful news! I’m not sure what release it was but EE is now bundling a `.htaccess` file inside the /templates directory that denies all web traffic. This is half the battle.
However, use caution, because this file is hidden in most OSs (and not selectable). If you’re copying files up to a server just make sure that `.htaccess` moves over. OR, if you’re using your own directory to store templates, make sure you copy their `.htaccess` into your templates directory to gain the same level of security.
steve — 17:38 on 02.02.2011
hi, I buy the Securing ExpressionEngine 2, in the page 14, I really confused about folders:
1) why use simply “sys” for the “system” folder ? that is to obvious? use “sys”, and why use admin.php for access to “sys”, admin.php is too obvious? if anybody know that a site are powered by ee, he know that can see the cpanel going to admin.php and he have in my that system are called “sys” and is outside the public_html, Im really confused, for me is not secure… is too obvious.
why not call the admin.php for something random name like “dychadjefu.php” and called the “system” folder for some random name like “kaumbepiph” too ?
admin.php and sys is too obvious not?
2) the folders that you suggest create:
lib
pub
sql
src
sys
tpl
are outside from my public_html right? (in my server I see a public_html) if yes! and you suggest call pub the public_html, how can rename it? I rename it, but my site dont load… need the public_html. I can rename on the cpanel or something?
I have that: see this please, is ok:
http://img151.imageshack.us/img151/5334/screenshot20110202at321.png
3) the goal of put the templates outside the public_html is that people can access to my templates right?