Use a custom domain name as a way to secure your Magento administrative panel

After this year 2015 full of security issues (SUPEE-6482, SUPEE-6285,SUPEE-6237, SUPEE-5994, SUPEE-5344) we have seen that there is many websites which only use the custom routing to hide the administrative panel; it means, back-offices are available from the front webservers with a string in URL as element to identify you wants to access to the admin panel.

And by default this string is admin, a not very difficult element to find :).

In this case, we are not very far from default behaviour, and everyone can access from your website to your back-office login form. And if you do not have admin accounts automatic locking (like the community edition does) you encounter risks of brute force logging attempts. And if someone earn back-office access, he will:

  • delete your customers accounts?
  • close your websites?
  • Spam your customers?
  • Install an incompatible module from Magento connect which will break your site?

All these can affect your brand image.

But there is some ways to make more secure the Magento admin panel. One of them, its to use a custom domain name for your back-office: it has the main advantage to allow you to customize security rules.

Just a few of configuration are required. You’ll find them bellow.

This article expect that

  • Your Magento webserver is hosted on a unix debian like operating system.
  • Your webserver is Apache.
  • Your Magento website is defined in the /etc/apache2/site-available/magento.conf file
  • Your back-office is available on the HTTP protocol.
  • For now, you access to your back-office from the www.mywebsite.com/customadminpath URL.
  • You wants to move it to the URL admin.mywebsite.com/customadminpath

The Magento configuration inherit mechanism

Before talking about the procedure to switch your back-office to a custom admin URL, just few words about how Magento manage URLs.

Magento come with it’s own concepts, and one of them is the ability to manage multiples websites and their internationalization within stores views.

When you display a page on Magento, you are in a store view. If you try to load a configuration value from this view, Magento first check if you have defined something for this store view. If yes, it use this value. If not, it check if you have defined something for the related website. If not, it’ll use the value set for the global scope. A concept you probably already know if you use Magento.

Back-office is a particularity of this concept: even if back-office is a store view, there is no hierarchy: the configuration used by the back-office view are the values defined for the global scope.

Magento URLs are completely included in this configuration management:

  • admin URL is the URL defined on the scope default.
  • Your websites and stores views are the specificities defined for the related configurations levels.

So Magento configuration inherit mechanism offer everything to define a custom URL for your back-office. It should be a shame to do not use it. How can we migrate this configuration?

Configure a custom admin URL for your Magento back-office

Step 1: Ensure that your Magento front-office stores URLs does not use the configuration inherit mechanism

This step is required because if you still use the configuration inherit mechanism (eg: have just define the URLs on the global scope), when we’ll update the back-office URL your front office URLs will also be updated. it could be problematic πŸ™‚

The configuration of the Magento URLs is managed differently for secure (http) and unsecure (https) part of your website. We start with the unsecure part.

1.1 – Ensure that your Magento unsecure store URL(s) does not use inherit configuration

1.1.1: Go to the Magento administrative panel which manage URLs configuration

This configuration panel is located in the System > Configuration > General > Web > Unsecure URL tab. You should see something like this:

Screenshot of the interface in the Magento administrative panel which allow to manage URLs of your websites and stores

1.1.2: Iterate on each store view configuration

On the top left of the page, you have the store view selector (the select box which allow to define on which store view you are currently editing the configuration). on my Magento, I have:
Screenshot of the selectbox which allow to choose on which scope we work

1.1.3: Uncheck the configuration values for your URLs

Check for each store views from this selectbox the configuration of your unsecure URLs: make sure that the “Use website” is unchecked like in the screenshot bellow.
Screenshot of the Magento admnistrative panel: checkbox allow to customize the scope you are updating
If not, uncheck it and save configuration.

Repeat this step for each of the store views available (in my case, en_uk, en_us, fr_fr and the french store view for the b2b website).

To check if everything is ok, flush the cache block from the administrative panel System > Cache Management and browse with your web browser all of your stores: your(s) catalog(s) must be still available(s).

Your websites and store views use now a dedicated configuration value for the unsecure URL.

1.2 – Ensure your secure store URLs does not inherit configuration

Repeat the steps 1.1.1, 1.1.2, and 1.1.3 for your secure URLs configuration (available from System > Configuration > General > Web > secure URL tab).

When you’ll finished, you can validate with your web browser (after flushing cache block cache mangement) that for each of your store views the customer accounts and checkouts are still available.

Step 2: Ensure that your Magento cookie policy is able to handle a new admin URL

Ok, now you do not use anymore the inherit mechanism for both http and https URLs. But it’s not yet finish with the configuration: for now, your cookie policy is able to handle both your front and back-office queries. But if we update our back-office domain name and leave the cookie policy as it, back-office could be unavailable. Wrong not?

We have to also update this domain name cookie configuration

This step is only required if you have for some of your store view(s) or website(s) defined a custom cookie domain. But by default, the cookie domain accept everything. If you have not updated it, you can go directly to step 3 but I think it’s however interesting to take time to check this configuration.

2.1 – Ensure that configuration for cookie domain for your front-office store views does not depends of the default cookie domain configuration

Go now in the menu System > Configuration > General > Web > Cookie Management and make sure that the value set for each store is like we have done for the URL management: For each store, uncheck the “use website” checkbox and save configuration.

Use a custom cookie domain for session cookie

We are now sure that our configuration for our front office store views is specific.

2.2 – Ensure that the cookie domain configuration for the admin is able to handle both new and current domain names

For the back-office scope (scope default), make sure to select a cookie domain value which is acceptable by both your new admin URL and your current URL: since we’ve not updated the admin configuration URL, we need to be able to browse back-office. And when we’ll update it, we must also be able to do it. If not, when we’ll update the admin URL, we won’t be able to connect to the back-office because session will not be available.

Cookie domain is configurable from the administrative panel on the fieldset General > Web > Session Cookie Management. Ensure that you’ll update configuration value for the default scope!

in this example we should set something like .mywebsite.com, witch match both admin.mywebsite.com and www.mywebsite.com.

If there is no shared domain name between current and the future back-office URL, you must set . as cookie domain. This is less secure, but it’ll work in each case.

After updating this configuration value, log out from back-office, close your browser, and log in a second time. You should still be able to browse back-office.

Step 3: Update Apache configuration to define your custom admin back-office URL

Now Magento is ready to accept a new URL for the back-office. Before setting this new value in Magento back-office, we have to update Apache configuration: if not, when we send a request to our webserver with the new URL admin.mywebsite.com, we’ll try to access to a webserver unknown by Apache and we have an unexpected answer.

A good starting point could be to copy your current front-office configuration file to a new one to define the specificities to the admin server:

root@your_web_server:~$ cp /etc/apache/sites-enabled/magento.conf /etc/apache/sites-available/magentoadmin.conf && sed "s|ServerName *www.mywebsite.com|ServerName admin.mywebsite.com|g" --in-place='.bak' /etc/apache/sites-available/magentoadmin.conf && ln -s /etc/apache2/sites-available/magentoadmin.conf /etc/apache2/sites-enabled

The file /etc/apache2/sites-enabled/magentoadmin.conf should contains something like this:

<Virtualhost XXX.YYY.ZZZ.TTT:80>
      ServerName admin.mywebsite.com
      DocumentRoot /a/path
      <Directory /a/path>
           # your magento configuration here
      </Directory>
</VirtualHost>

You should force Magento to load the admin panel when a request is sent to admin.mywebsite.com by using the following server variables in this file:

<Virtualhost XXX.YYY.ZZZ.TTT:80>
      ServerName admin.mywebsite.com
      DocumentRoot /a/path
      <Directory /a/path>
      # your magento configuration here
      # force loading the admin store
      setEnv MAGE_RUN_CODE admin
      setEnv MAGE_RUN_TYPE store
      </Directory>
</VirtualHost>

Don’t forget to check if everything is ok in your apache configuration with the following command:

user@your_web_server:~$ apache2ctl configtest

If the output is ok, restart apache with the following command:

root@your_web_server:~$ apache2ctl restart

Now, Your apache webserver know what to do if it receive a request for admin.mywebsite.com

Step 4: Resolve your new Magento administrative panel domain name

The final preparation step is to explain to your desktop or all required back-office users that http://admin.mywebsite.com must be managed by your webserver. If not, your browser can ask http://admin.mywebsite.com but don’t know where going to find the appropriate answer.

4.1 – Check that domain resolution for your future admin webserver is not fine enough

I’ll give you two methods to check if your Magento admin domain name resolution is able to handle your admin configuration domain name yet:

  • by ping command
  • using your browser.
4.1.1: Check your future admin domain name resolution using the ping command

Open a terminal from your computer, and ping your new admin hostname with the following command:

user@your_web_server: ping admin.mywebsite.com

If you have an output like this:

ping: unknown host admin.mywebsite.com

You have to configure a DNS resolution for your admin.

4.1.2: Check your future admin domain name resolution with your browser

You can also check if your browser is able to resolve it by opening a new window (or tab) and open the URL http://admin.mywebsite.com

If your browser tell you that it cannot resolve it, you’ll have to made the DNS resolution

Screenshot of chrome browser output when domain name resolution is not found

Screenshot of firefox browser output when domain name resolution is not found

4.2 – Set up your domain name resolution for your Magento future administrative panel

it can be done:

  • For you current desktop:
    • In your %windows_folder%/System32/Drivers/etc/hosts file if you are on windows.
    • In your /etc/hosts file if you are on Linux based distribution.
    • For MAC users, my bank loan have been refused, I don’t have MAC πŸ™‚ (but I suppose it’s also in /etc/hosts file).
  • For different users:
    • In your DNS record.

After that, a

user@your_web_server: ping admin.mywebsite.com

must answer something like this:

PING admin.mywebsite.com (XXX.YYY.ZZZ.TTT) 56(84) bytes of data.
64 bytes from admin.mywebsite.com (XXX.YYY.ZZZ.TTT): icmp_seq=1 ttl=64 time=0.024 ms
64 bytes from admin.mywebsite.com (XXX.YYY.ZZZ.TTT): icmp_seq=2 ttl=64 time=0.029 ms
64 bytes from admin.mywebsite.com (XXX.YYY.ZZZ.TTT): icmp_seq=3 ttl=64 time=0.029 ms
64 bytes from admin.mywebsite.com (XXX.YYY.ZZZ.TTT): icmp_seq=4 ttl=64 time=0.029 ms

and opening URL http://admin.mywebsite.com/customadminpath in your favorite browser should display the Magento login form

Now everything is ready!. Let’s go and update our back-office URL

Step 5: Update Magento configuration to set the new back-office URL

So go in your current back-office and open the System > Configuration > General > Web > Unsecure URL tab: replace now in scope default the web unsecure URL by http://admin.mywebsite.com/. (Don’t forget to add the trailing / add the end of the URL).

Save config

Log out from the back-office

And open the http://admin.mywebsite.com/ URL. You should set the login form

Secure your back-office URL

Does your back-office is secured now?

It’s a shame but no:

  • Login form is still available from http://www.mywebsite.com/customadminpath
  • Everyone able to access to http://admin.mywebsite.com will be able to view the Magento login form.

Try it: open your old admin URL http://www.mywebsite.com/customadminpath/ you’ll still view the login form :(. The only thing we have done for now is to redirect people which provide valid login credentials to http://admin.mywebsite.com/customadminpath

Add the following rewrite rule in the Apache configuration file of the website virtualhost /etc/apache2/sites-available/magento.conf will redirect each user who try to access to admin from http://www.mywebsite.com/customadminpath/ to the admin domain name http://admin.mywebsite.com/:

<Virtualhost XXX.YYY.ZZZ.TTT:80>
      ServerName www.mywebsite.com
      DocumentRoot /a/path
      # redirect users to admin domain name if they try to access for login from website
      <IfModule mod_rewrite.c>
                RewriteEngine On
                RewriteCond %{HTTP_HOST} www.mywebsite.com [NC]
                # replace customadminpath by your own admin query string
                RewriteCond %{REQUEST_URI} ^.*/customadminpath/.*$
                RewriteRule ^(.*)$ http://admin.mywebsite.com/ [R=302,L]
      </IfModule>
      <Directory /a/path>
            # your magento configuration here
      </Directory>
</VirtualHost>

After an Apache restart, your login form is only available from http://admin.mywebsite.com

This is not the object of this post, but many things can be done to improve the ACL of your back-office. For example:

Is there an interest to use a custom domain name if you use the default behavior? I mean yes, and quickly.

Is there an interest to use a custom domain name if you already use something different than admin as suffix to access to your back-office? I mean yes. For sure, it’s quite more difficult to find it, but security issues have shown that it’s easily to find these “hidden” back-offices: Security through obscurity is not security. it’s just security for some times.

Patch against the Magento’s SUPEE-6482 issue

Hello everyone,

I know this is the holidays and you have probably only sun in mind, but security issues can’t wait: this morning Magento have published a new patch against SUPEE-6482 issue which include two issues related to APIs and two cross-site scripting risks.

Continue reading “Patch against the Magento’s SUPEE-6482 issue”

A custom Magento patch file to take care of your specificities?

If – as me – you’ve set Magento patchs file webpage as your browser favorites or if you don’t remember the last time you saw a notification in your back-office which does not concern a security issue, this blog post is for you πŸ™‚

A few weeks ago, I warned you compared to the sense of security that can provide the application of security patches Magento : this is not because you have installed Magento patch files that you are secured: if vulnerable files have been overloaded either by a module coming from Magento connect or by custom development, this is this this file which is used by Magento and which needs to be patch.

So it means Continue reading “A custom Magento patch file to take care of your specificities?”

Are you still vulnerable after applying a Magento security patch?

Screenshot of the popin displayed in your back-office which notify about security patches

I salute Magento and all its partners for the notifications about security issues found.
Magento notify you in the back-office with some notifications.

These patchs are all available from the Magento download page and are distributed under a .sh file. You have just to run mypatchfile.sh and that’s it, you are secured!?

NO! Continue reading “Are you still vulnerable after applying a Magento security patch?”

How to patch PROPERLY Magento Zend Framework XML-RPC security issue?

On July, 5th, 2012, an important security issue has been highlighted in Zend Framework, and so in Magento. This issue allows people to read almost any file on your webserver. A very dangerous issue, that’s why it must be patched quickly

Tell me, how can we patch it?

Oh nice, there is a patch available. I open it, and now, I have some red spots appearing on my body: they edited the embedded Zend Framework and Magento core sources…. Almost everybody agree that we do not edit the Magento sources files. Why do it there?

A common workaround about Magento overloading is the following one: use local to patch Magento and Zend Framework files. We’ll use this way to patch the XML-RPC issue instead of editing Magento sources files

The following script updatepath.sh init your Magento so it can patch this way. It works with the provided patch file for CE 1.5 to 1.7 Magento version

#!/bin/bash
##################################
# config
##################################
LOCAL_FOLDER="app/code/local";
RESPONSE_FILE="Zend/XmlRpc/Response.php";
RESPONSE="$LOCAL_FOLDER/$RESPONSE_FILE";
REQUEST_FILE="Zend/XmlRpc/Request.php";
REQUEST="$LOCAL_FOLDER/$REQUEST_FILE";
PATCH_FILE="CE_1.5.0.0-1.7.0.1.patch";
DESTINATION_PATCH_FILE="kyp_$PATCH_FILE";
###################################
# process
###################################
# check if patch file already exists
if [ ! -f $PATCH_FILE ]; then
    echo "Patch file $PATCH_FILE does not exists. Please download it at http://www.magentocommerce.com/blog/comments/important-security-update-zend-platform-vulnerability/";
    exit 2;
fi
# create local folder if not exists (eg: CE1.7 and related EE)
if [ ! -d $LOCAL_FOLDER ]; then
   echo "Init app/code/local folder";
   mkdir $LOCAL_FOLDER
fi
# create folder for Zend Framework Response file patch
if [ ! -d "$LOCAL_FOLDER/Zend/XmlRpc" ]; then
    echo "Creating Zend/XmlRpc local folder";
    mkdir -p "$LOCAL_FOLDER/Zend/XmlRpc";
fi
if [ -f $RESPONSE ]; then
    echo "File $RESPONSE already exists. Please append patch in";
    exit 1;
fi
echo "copying $RESPONSE_FILE in local folder";
cp lib/$RESPONSE_FILE $RESPONSE;

if [ -f $REQUEST ]; then
    echo "File $REQUEST already exists. Please append patch in";
    exit 1;
fi
echo "copying $REQUEST_FILE in local folder";
cp lib/$REQUEST_FILE $REQUEST;
# update patch file to replace lib by app/code/local
echo "Update patch file"
sed "s|lib/|app/code/local/|g" $PATCH_FILE > $DESTINATION_PATCH_FILE
echo "new patch file $DESTINATION_PATCH_FILE has been generated. You can now apply it with patch -p0 < $DESTINATION_PATCH_FILE"

This way, you are sure that your Magento will always be patched, even if you upgrade to a prior version than 1.7.0.2 CE (first release which embedded the patch)

The only way it won't work is if you load Response.php and Request.php files with a requirement to full path to lib folder, but this is not the Magento best practices

how to solve Magento message “Your web server is configured incorrectly. As a result, configuration files with sensitive information are accessible from the outside. Please contact your hosting provider.”

If you have this message when you are logged in your back-office, it’s because there is a misconfiguration in your Magento host. There are multiple reasons to have this message, and multiple ways to fix it

Why do I have this message displayed?

Since 1.4.2 version, back-office check from back-office if file app/etc/local.xml can be read through a browser (If the response code is a Apache 200 response code; This control is made by a CURL request on your unsecure_base_url/app/etc/local.xml URI) It’s very important not to be able to read this file from a webbrowser, because it contains your database parameters, cache and session configuration.

All files and folders in app folder are protected by a .htaccess file which denies access from everyone since it browses your Magento directory tree starting from the app folder:

Order deny,allow
Deny from all

this directive is applied starting from .htaccess path and covers also subfolders, and so, local.xml file

Origins of the problem

.htaccess usage can be disturbed for three major reasons:

htaccess file doesn’t exist

For sure, if htaccess file does not exist, there is no restriction on who can read the local.xml file, and so, the security warning is displayed

htaccess files are not the access filename

By default in Apache configuration, the AccessFilename is set to .htaccess. It can be updated with the AccessFilename directive in webserver or virtual host configurations files.

So if value has been updated, .htaccess will not be read, and so ACL is not used

But if this is your study case, you should have more complex problems with your Magento πŸ™‚

Cannot override the directories acccess control list

Apache configuration allows also to define which rules can be overrided in AccessFilename with AllowOverride directive

If you are a hosting provider, perhaps you don’t want that your clients can update in their AccessFilename some security directives. It can be done with the AllowOverride directive

Have a look at the official documentation to see the possible values for this directive

In this case, if AllowOverride directive is not well set, the .htaccess file is read, but the ACL defined is not used, and so, we can have access to your local.xml file

Because this directive is applied only to <Directory;> instruction, you must be able to edit the vhost configuration file to fix this issue. Ask your hosting provider if you cannot

Specifics rewriting rules

For one client, we encounter this case: we have updated some elements of the Magento directory tree and define some specific rewriting rules. local.xml file was not available, but CURL test receive a 200 error code because of a rewriting rule.

In this case, this is the test which is involved, not your security policy

Conclusion

Configuration is checked on the app/etc/local.xml file, but other sensibles informations can be fetch from your app directory

It’s a shame that everybody doesn’t take care of this security issue. Take a look at the google results, you’ll be surprised

If your configuration is well set, when you request the app/etc/local.xml file on your Magento, you should have the following error displayed

Magento: protect you from XSS

Few time ago, NBS System, a french Magento hosting, has published a reporting about some XSS issues available on Magento

My curiousity led me to check some references on Magento, and It’s a shame, but there are many which are vulnerable.

  • Is it a lack of sensibility to this issue in web agencies ?
  • A maintenance too weak or not proactive enough ?

Some of these websites are online for many years. It’s a shame that web application security was not considered better.

Unix permissions policies on Magento

Recently, Prestashop has been attacked by a worm: this worm uploaded on the server was able to update the content of a template; this template load many iframe which make you request some unexpected things. Many users have been infected. According to the first feedback, it seems that a good unix permissions policy on Prestashop folder could have stopped this infection.

Magento‘s hosted on unix servers seem to have the same problem: even if there is – for the moment – no problem like Prestashop’s one, most of the plateforms I saw have unix permissions policy problems, and so provide attack facilities. This is the reason why I wrote this article.

Unix permissions resume

First remember the basic of unix permissions: For files and folders, they define if:

  • You can read a file / folder
  • You can write or delete a file / write in this folder
  • You can execute this file / browse the folder

They are defined for three users groups:

  • owner of the resource
  • one group of user
  • other users which are neitherbowner, nor member of the group defined

With this combination of users groups and roles, we can set the most common access permissions on our magento. But which one is the most secured one?

Unix permissions and Magento deployments methods

Permissions set are closely linked to your deployment method: Do you:

  • Upgrade magento directly with Magento connect?
  • Use the installer setup process and deploy your data with magento’s installers?
  • Copy a database coming from a previous server and update the configuration?

In the following article I’ll take the option that you test your updates on a non production server, push your source code through FTP, svn, or other file mechanism, and push your database upgrades with magento installers. Then, I’ll explain you which updates you require to be able to use other delivery mechanism.

Unix permissions Magento requirements

Unix permissions for Web server user in Magento

The most important thing from the point of view of your server security is the permissions defined for the owner of the files: this user run a server, so accept connexions. We must control which services can be provide by this server.
In most of the case this user is the user which run the webserver.

Common rules to apply

First, we will check what is requested for the webserver user to be able to use normally Magento scripts: this user needs to be able to read all files (this is the only requirement to be able to use PHP script) and be able to browse the magento directory tree. That’s all. So your PHP scripts must not have more than 4 octal permission. For your directory tree, we will give to your account access to read and browse, so 5 octal permission.

This is the most common structure for all Magento’s files and folders. Now we will take a look at some special cases.

Folders which require to be writable

Take a look now at the var and media subfolders; webserver user will write there its own data:

  • in var subfolder, he will write: backup files, log files, perhaps cache file, session user files, index process lock files, etc.
  • in media subofolder, he will write thumbnails and media librairy

So these two subfolders require the write permission.

Executables scripts by Webserver user

The question is : does your webserver user require to be able to execute scripts?
Depending on your Magento version, only two or four files require to be executable:

  • Installer script (pear for 1.4.2 or lower,Β  mage for the earlier versions): all to install modules from magento connect, or to be able to update directly from magento connect your magento
  • scheduler entry point cron.sh
  • pear embedded
  • pecl embedded

In our deployment model, pear is not used from back-office: so we do not set executable permission for our webserver to our webserver user: mage / pear / pecl won’t be executable by this user.
If you want to run scheduled tasks with this user, you must set up executable on the cron.sh file. But you can also run scheduled tasks with another account and so remove also this permission on this file for this user.

Unix permissions for group in Magento

Which group content ?

With group user, we will define all the permissions for administratives tasks: deploy, upgrade, maintenance management, etc.
This allow us to be really independant of the webserver user permissions.
So the group choice depends on who run these tasks. Most common thing is to set up the group of the administrative user as group.

Be able to upgrade source code

To be able to upgrade source code, this group must be able to write in all magento folders, delete, read files.

Be able to manage var data

Unix permissions for all others users in Magento

If all others users are not the owner of the file nor part of the group which realize the administrative tasks, they should not be able to access Magento directory tree: so no permissions

Unix permissions for others deployment methods

Deployment method with Magento connect

No, do you really update your source code from magento connect? Hope I won’t be on your website when you’ll do an upgrade πŸ™‚

But anyway, in this case because it’s the webserver user which run magento connect, you must:

  • Give read / write on all files and folder (packages potentially contain files which can go in every folder).
  • Give the ability to execute mage / pear / pecl

This is one of the reason I don’t recommand this method: all your source files are potentially writeable by webserver user, and so, can be editable like in Prestashop worm.

Initial setup starting with Magento install program

In this case, there’s no big difference with the way I explained before: the only difference is on the app/etc/ folder which must be writeable during installation process to allow creation and update of the local.xml file. Then, when installtion process will finish, you can remove the write access on app/etc and app/etc/local.xml file.

Conclusion

You can find here a summary of the policy we should apply on our Magento folder.

#!/bin/bash
# 
# edit the following variables according with your server configuration
#
ROOT_UID="0"
GROUPUSERNAME=your_group
WEBSERVERUSERNAME=httpd
#
#Check if run as root
#
if [ "$UID" -ne "$ROOT_UID" ] ; then
   echo "You must be root to do that!"
   exit 1
fi
#
# ok, let's go for setting up permissions
#
chown $WEBSERVERUSERNAME:$GROUPUSERNAME "./*" -R
find . -type f -exec chmod 0460 {} \;
find . -type d -exec chmod 0570 {} \;
find var -type f -exec chmod 0660 {} \;
find var -type d -exec chmod 0770 {} \;
find media -type f -exec chmod 0660 {} \;
find media -type d -exec chmod 0770 {} \;
# set up installer script for our admin account
if [ -f pear ]; then
    chmod 0570 pear;
else 
   if [ -f mage ]; then
     chmod 0570 mage;
   fi
fi
if [ -f cron.sh ]; then
   chmod 0570 cron.sh
fi