December 06, 2010

Securing Magento
By default most software packages are installed with the most lenient file/directory permissions and ownership. This is normally done for the sake of the software developer given that their software must be installed on a range of diverse systems with varying configurations. This article is meant to give you an overview of how to setup your Magento installation with the strictest of permissions for overall security’s sake.
When running Linux there are two main environments that you will find:

  1. PHP scripts that run via mod_php or equivalent and all scripts are executed as the webserver user. This means that when your script is running it can read (and sometimes write) with the same privilege level as the web server. This could allow cross-account snooping in shared hosting setups and is not ideal in a shared environment especially when it comes to e-commerce.
  2. PHP scripts that run as the user who owns the files themselves via an intermediate construct such as suPHP, PHP suEXEC, PHP-FPM etc. In this case your scripts run as you and is a more secure overall configuration when running on a shared server.

Running As The Webserver User (#1)

NOTE: These instructions are meant to be used with Magento Enterprise. If you are going to do the following with Magento Community Edition then this will effectively break the Magento Connect functionality. That said we’ve included a script to turn on and off these changes should you wish to use these instructions flexibly.
By default many shared and dedicated hosting companies run your scripts as the webserver user itself as stated above. It’s the operating system default on most Linux systems and while in a shared environment it’s not the most secure it can be partially remedied. This is done by limiting access via more strict file permissions which mitigates some of the inherent security issues. In dedicated hosting environments this method is actually desirable, mainly for performance reasons, and all of our dedicated and clustered Magento SIP plans use this method. None of the shared hosting caveats apply for dedicated servers given that the server is serving a single client.
These are the steps we take in plain English followed by the script commands:

  1. If you have access to change the ownership of files and directories (normally meaning you have root access) then set the user and group ownership of all files in the Magento directory to your local user. This may already be done in your environment and is simply a precaution for good measure to flush out any webserver owned files or directories.
  2. [bash]find \-exec chown youruser.youruser {} \;[/bash]

  3. Change the Linux permissions for all files in your Magento base directory to readable and writable by the owning user (you) and readable only by everyone else. This is to get a baseline where the webserver itself can read all files. It will need read access in order to execute scripts and serve static content like images, CSS and Javascript files.
  4. [bash]find -type f \-exec chmod 644 {} \;[/bash]

  5. Change the Linux permissions for all directories in your Magento base directory to list-able, file editable and navigable for the owning user and simply navigable for everyone else.
  6. [bash]find -type d \-exec chmod 711 {} \;[/bash]

  7. The “media” and “var” directories require special handling since the webserver itself must be able to both read and create/edit files. This is where most instructions give away the farm and go straight for world editable permission on files and directories. We’ll take a least privileged approach by changing the Linux permissions for all directories to list-able, file editable and navigable by the owning user and just navigable by everyone else. We’ll also take the extra step of setting the Linux “group” permissions on the file so that anyone in the group can list, edit files and navigate the directories as well.
  8. [bash]find -type d \-exec chmod 775 {} \;
    find -type d \-exec chmod 775 {} \;[/bash]

  9. We’ll do something similar for the files in the “media” and “var” directories as well. That is allow the owning user read and write permissions, the group user read and write permissions and everyone else simply read permissions.
  10. [bash]find -type f \-exec chmod 664 {} \;
    find -type f \-exec chmod 664 {} \;[/bash]

  11. This step will also require either root level access or a flexible hosting company (like us). You will need to set the file and directory ownership for the “media” and “var” directories to be owned by the webserver and have group ownership to your local user. You could argue that this is backwards but for technical reasons involving how we calculate disk space usage this is how it’s recommend and done on our systems.
  12. [bash]find \-exec chown webuser.youruser {} \;
    find \-exec chown webuser.youruser {} \;[/bash]

  13. This step again will require root access and/or a flexible host and is probably the least understood of all of the steps. In steps 5 and 6 we’ve setup a system whereby you are allowing the webserver access to read and write your files but in a way that is very specific – which is a good thing. We’ve done this on a specific set of existing files and directories. We need to ensure that future files and directories created follow an equal (or more strict) set of ownership and permissions. This is done by using some special features of Linux directories, namely the SUID and SGID bits. These bits, when set, tell Linux to inherit the ownership of the directory which immediately encompasses the file or directory being made. Simply, as Magento creates files and directories in “media” and “var” their ownership will mirror what we set in step 6.
  14. [bash]find -type d \-exec chmod u+s,g+s {} \;
    find -type d \-exec chmod u+s,g+s {} \;[/bash]

  15. Finally, for a minimal amount of added protection against snoopers change the file permissions on the core Magento configuration files to be readable and writable by the file owner and readable by the group only.
  16. [bash]chmod 640 [/bash]

Magento web user permissions script:
[code language=”bash”]
#!/bin/bash
if [ ! -f ./app/etc/local.xml ]; then
echo "– ERROR"
echo "– This doesn’t look like a Magento install. Please make sure"
echo "– that you are running this from the Magento main doc root dir"
exit
fi
if [ `id -u` != 0 ]; then
echo "– ERROR"
echo "– This script should be run as root so that file ownership"
echo "– changes can be set correctly"
exit
fi
echo -n "Enter the local UNIX account user (ftp user): "
read user
echo -n "Enter the local UNIX webserver user (normally ‘apache’): "
read webuser
if [ ! `id -u $user` ]; then
echo "– ERROR"
echo "– No such user: $user"
exit
fi
if [ ! `id -u $webuser` ]; then
echo "– ERROR"
echo "– No such user: $webuser"
exit
fi
find . \-exec chown $user.$user {} \;
find . -type f \-exec chmod 644 {} \;
find . -type d \-exec chmod 711 {} \;
find ./media -type d \-exec chmod 775 {} \;
find ./var -type d \-exec chmod 775 {} \;
find ./media -type f \-exec chmod 664 {} \;
find ./var -type f \-exec chmod 664 {} \;
find ./media \-exec chown $webuser.$user {} \;
find ./var \-exec chown $webuser.$user {} \;
find ./media -type d \-exec chmod u+s,g+s {} \;
find ./var -type d \-exec chmod u+s,g+s {} \;
chmod 640 ./app/etc/*.xml
[/code]
That’s all there is to it. Doing the above will give you some of the tightest permissions available on a Magento install.

Running As Your Local User (#2)

In shared environments this method is preferred given the extra level of security provided by Linux if the permissions are configured correctly as we’re going to do. All of our shared Magento SIP plans provide this environment and it is preferred given that is provides user-based permissions isolation so stricter ownership and file permissions can be used.
These are the steps we take in plain English followed by the script commands:

  1. If you have access to change the ownership of files and directories (normally meaning you have root access) then set the user and group ownership of all files in the Magento directory to your local user. This may already be done in your environment and is simply a precaution for good measure.
  2. [bash]find \-exec chown youruser.youruser {} \;[/bash]

  3. Change the Linux permissions for all files in your Magento base directory to readable and writable by the owning user (you) and readable only by everyone else. This is to get a baseline where the webserver itself can read all files. It will need read access in order to serve static content like images, CSS and Javascript files. Unlike the method above we’ll be adjusting script permissions to be more stringent in step 4.
  4. [bash]find -type f \-exec chmod 644 {} \;[/bash]

  5. Change the Linux permissions for all directories in your Magento base directory to listable, file editable and navigable for the owning user and simply navigable for everyone else.
  6. [bash]find -type d \-exec chmod 711 {} \;[/bash]

  7. Wrench down permissions for all PHP scripts so that only your user can read them. This is ideal because only your user should need to know the contents of scripts.
  8. [bash]find -type f -name “*.php” \-exec chmod 600 {} \;[/bash]

  9. Finally, and this is the nicest part about using this method, disable all access to your local configurations files for Magento except to yourself. Since the PHP scripts are the only thing that need to read these files and PHP is running as you then you can disable access to all others which is very nice!
  10. [bash]chmod 600 [/bash]

Magento local user permissions script: –
[code language=”bash”]
#!/bin/bash
if [ ! -f ./app/etc/local.xml ]; then
echo "– ERROR"
echo "– This doesn’t look like a Magento install. Please make sure"
echo "– that you are running this from the Magento main doc root dir"
exit
fi
if [ `id -u` != 0 ]; then
echo "– ERROR"
echo "– This script should be run as root so that file ownership"
echo "– changes can be set correctly"
exit
fi
echo -n "Enter the UNIX user which the Magento scripts should run as: "
read user
if [ ! `id -u $user` ]; then
echo "– ERROR"
echo "– No such user: $user"
exit
fi
find . \-exec chown $user.$user {} \;
find . -type f \-exec chmod 644 {} \;
find . -type d \-exec chmod 711 {} \;
find . -type f -name "*.php" \-exec chmod 600 {} \;
chmod 600 ./app/etc/*.xml
[/code]

One Final Note

I’ve seen many instructions for web based software that states that files must be 777 permissions (read/write/execute permissions to all). This may be necessary for some directories but is rarely right for files. Permissions of 666 (read/write permissions for all) are adequate in these cases (if more strict permissions cannot be set). 777 permissions sets the execute bit on files as well which most web servers don’t (and shouldn’t) require in most cases. Setting 666 permissions simply says “read and write for all users” which isn’t great either but is more correct.
Permission reset script: (applicable to both methods above)
[code language=”bash”]
#!/bin/bash
if [ ! -f ./app/etc/local.xml ]; then
echo "– ERROR"
echo "– This doesn’t look like a Magento install. Please make sure"
echo "– that you are running this from the Magento main doc root dir"
exit
fi
if [ `id -u` != 0 ]; then
echo "– ERROR"
echo "– This script should be run as root so that file ownership"
echo "– changes can be set correctly"
exit
fi
echo -n "Enter the UNIX user which the Magento scripts should run as: "
read user
if [ ! `id -u $user` ]; then
echo "– ERROR"
echo "– No such user: $user"
exit
fi
find . \-exec chown $user.$user {} \;
find . -type f \-exec chmod 644 {} \;
find . -type d \-exec chmod 711 {} \;
find . -type f -name "*.php" \-exec chmod 600 {} \;
chmod 600 ./app/etc/*.xml
[/code]

Nexcess
Nexcess

Nexcess, the premium hosting provider for WordPress, WooCommerce, and Magento, is optimized for your hosting needs. Nexcess provides a managed hosting infrastructure, curated tools, and a team of experts that make it easy to build, manage, and grow your business online. Serving SMBs and the designers, developers, and agencies who create for them, Nexcess has provided fully managed, high-performance cloud solutions for more than 22 years.


We use cookies to understand how you interact with our site, to personalize and streamline your experience, and to tailor advertising. By continuing to use our site, you accept our use of cookies and accept our Privacy Policy.