Community Documentation

Securing file permissions and ownership

Last updated February 10, 2012. Created by lsrzj on April 10, 2008.
Edited by Charles Belov, ursula, greggles, jhr. Log in to edit this page.

The server file system should be configured so that the webserver (e.g. Apache) does not have permission to edit or write the files which it then executes. That is, all of your files should be 'read only' for the Apache process, and owned with write permissions by a separate user.

As a quick test to confirm whether your site is secure or not you can run the Security Review module.

Note that this whole article is about "defense in depth." Drupal can run quite safely with permissions a little "looser" than they should be. But if an administrator account is compromised by an attacker or an attacker gains the ability to execute arbitrary code then the configuration below will limit their ability to further exploit your site.

Configuration examples

For example, on many systems the Apache process runs as a user called "www-data". This user should be able to read all of the files in your Drupal directory either by group permissions or by "other" permissions. It should not have write permissions to the code in your Drupal directory. If you use features of Drupal which require the "files" directory, then give the www-data user the permission to write files only in that directory.

Following is an example file listing of a safe configuration showing two files in a site where uploaded files are stored in the "files" directory. In order to see the file permissions set for your set-up, go to the command line and type: ls -al.

drwxrwx---  7 www-data    greg-group  4096 2008-01-18 11:02 files/
drwxr-x--- 32 greg-user   www-data    4096 2008-01-18 11:48 modules/
-rw-r-----  1 greg-user   www-data     873 2007-11-13 15:35 index.php

In the above example, the web server user has the ability to write in the files directory, any users in the group "greg" can read and write the data as well, but other users are not allowed to interact with that data. The "index.php" file (representative of all code files) can be edited by "greg" and can be read by the www-data group (we assume the www-data user is in the www-data group). No other users can read that file. This is a fairly secure method of configuring your site. You generally don't want random users who have the ability to read files on your server to see inside those files, hence the last three permissions are --- instead of r-x.

Below is an insecure setup:

NOTE: THIS IS AN INSECURE CONFIGURATION
drwxrwx---  7 www-data  www-data  4096 2008-01-18 11:02 files/
drwxrwx--- 32 greg-user www-data  4096 2008-05-16 11:48 modules/
-rw-rw-rw-  1 www-data  www-data   873 2007-11-13 15:35 index.php

This configuration allows the www-data user to edit the index.php file (and since it is representative of other files, we assume every file that makes up the Drupal site). This configuration is dangerous for the reasons outlined below. If you are using a configuration like this, please change it immediately to be more like the first version.

Quick lesson in permission's numeric equivalents

Special numbers mean less than "read write execute".
In general, special numbers like "4 means read, 2 means write, and 1 means execute" are less useful than "r means read, w means write, and x means execute."

However, some folks/software need numbers so:

rwxrwx--- is also 770
The order represents user-group-other. More information on permissions can be found later in this document.

How insecure permissions are a problem

If you allow your site to modify the files which form the code running your site, you make it much easier for someone to take over your server.

Worst case scenario: a file upload tool in Drupal allows users to upload a file with any name and any contents. This allows a user to upload a mail relay PHP script to your site, which they can place wherever they want to turn your server into a machine to forward unsolicited commercial email. This script could also be used to read every email address out of your database, or other personal information.

Undesirable scenario: if the malicious user can upload a file with any name but not control the contents, then they could easily upload a file which overwrites your index.php (or another critical file) and breaks your site.

Undesirable scenario: if the code allows users to see the contents of files, attackers could see information which might reveal potential attack vectors.

If you are a sysadmin

Note for hosted Drupal installations

It's important to notice that the user ownership of Drupal's core directories/subdirectories and files is given to the user who administrates Drupal (usually root) and group ownership is given to the group your apache is running on. For files and directories inside the "sites" directory the user who is hosting the site on your server is their owner. The best way to do this is to delete the "sites" directory under Drupal's root directory and make it a symbolic link to /home or other path you use to store user's home directories. That way, if you create user names that matches the customer's site URL, no permission will need to be changed. The only thing to be done is to change the directory group ownership to the group your apache is running on.

cd /path_to_drupal_installation
mv sites/* /home
rmdir sites
ln -s /home sites
useradd www.example.com
chown
-R www.example.com:www-data /home/www.example.com

The apache permission is given through group permission and others have no access at all to any files and directories on a Drupal installation. Don't give in any way permission to others, otherwise if your system is hacked through a weak password of a given user, the hacker will access all files and directories of all installed sites on your server not only the one invaded. Even a read only permission must be avoided, remember that database user name and password for each site are stored in settings.php. Worse, if you give write permission to others, the hacker WILL alter files to damage your site or upload malicious scripts to your server.

The instructions in this guide assumes a non hosted installation, so modify the ownership as needed. So where you see greg, can be replaced by the user who administrates Drupal, usually root, but not necessarily.

Follow this guide exactly as it is to make your Drupal installation as more secure as possible. This guide was tested and works. If something goes wrong with your installation, review the steps, possibly you missed something. If it really doesn't work post a comment with your doubt, we will fix this guide.

Linux servers

To set the permissions all at once you can issue these commands from the Drupal root directory. I'm assuming that greg user is part of greg group and that greg is the site owner. Make sure you run the following commands from inside Drupal's root directory otherwise you will mess up all your filesystem's permissions.

[root@localhost]cd /path_to_drupal_installation
[root@localhost]chown -R greg:www-data .
[root@localhost]find . -type d -exec chmod u=rwx,g=rx,o= {} \;
[root@localhost]find . -type f -exec chmod u=rw,g=r,o= {} \;

The second command will give ownership recursively on Drupal's root directory for user greg and www-data group. Don't do this if you are in a hosted installation. To the Drupal's root files and directories the user root must be the owner, not greg.

The third command will find all directories and subdirectories on Drupal's root directory and execute a chmod that will change the permissions to read, write and access for user greg, read only and access to www-data group and none to others. Summarizing: rwxr-x---

The fourth command will find all files inside Drupal's directories and execute a chmod that will change the permissions to read, write for the user greg, read only for www-data group and none to others. Summarizing: rw-r---

Now for the "files" directories the permissions are slightly different because it must have write permission to the www-data group too:

[root@localhost]cd /path_to_drupal_installation/sites
[root@localhost]find . -type d -name files -exec chmod ug=rwx,o= '{}' \;
[root@localhost]for d in ./*/files
do
   find $d -type d -exec chmod ug=rwx,o= {} \;
   find $d -type f -exec chmod ug=rw,o= {} \;
done

The "for" loop above is writting for an sh-style shell (sh, bash,ksh). If you use csh or tcsh, type bash before executing the command.

These commands will give read, write and access for user greg and for www-data group and none to others(rwxrwx---) for all "files" directories inside Drupal's "sites" subdirectory and will give read and write permission for user greg and group www-data and none to others (rw-rw----) for all files found inside each "files" subdirectories.

Remember that any newly installed module/theme or whatever addon must have its permissions changed too, It's better to do this BEFORE installing it in its appropriate Drupal directory.

Addendum on chmod non numeric permission representation

Meaning of the signs:
"+" add a permission to the ones already assigned
"-" revoke a given permission maintaining the others already assigned
"=" ignores the already assigned permissions and gives the ones listed
"u" = user
"g" = group
"o" = others
"a" = everybody (user, group, others)

For files:
r = read
w = write
x = execute

For directories:
r = list (read directory contents)
w = write
x = can access the directory. Whoever has not an x for a directory can't make a cd to it.

Using chmod without numeric values makes it more human readable. Here some examples of how to use it:

chmod commands and results for a file with permissions rwxrwx--- (770)
chmod human chmod numeric resulting permission
ugo=rwx 777 rwxrwxrwx
u-wx 470 r--rwx---
o+r 774 rwxrwxr--
g-wx,o+r 744 rwxr--r--
u-w,g-wx,o+r 544 r-xr--r--
g=,o=r 704 rwx---r--
a-wx 440 r--r-----

Windows servers

By default, Apache runs in the built in SYSTEM account. So all you have to do is change the permission in a way that only the SYSTEM account, the administrators group and the user greg have access to the Drupal root directory, subdirectories and files (assuming greg is the site owner).

You should exclude all other users and groups from the ACL. For the SYSTEM account give read only access to all Drupal directories, sudirectories and files except for the "files" directories which require write permission. For the user greg give read, modify and write permissions. And for the administrators group give complete access. Go to the Drupal root directory, right click on it, go to properties and then security.

Make use of permission inheritance to make things easier for yourself. And remember that any newly installed module/theme or addon must have its permissions changed too. It's better to do this BEFORE installing it in its appropriate Drupal directory. For those who use permission inheritance it's done automatically by Windows.

Special considerations for settings.php

The settings.php file contains the database password and username in plain text and, once created, should be set so that only appropriate users can read it. That usually means removing read permissions for the "other" user.

Summarizing the permissions

  • drupal_admin: the user on the server that administrates Drupal, not necessarily is the root.
  • site_admin: the owner of the hosted site (a customer)

Ownership

Core modules/themes files and directories: drupal_admin:www-data
Hosted sites modules/themes/files files and directories: site_admin:www-data

Permissions

Core modules/themes directories: rwxr-x---
Core modules/themes files: rw-r---
Hosted sites modules/themes directories: rwxr-x---
Hosted sites modules/themes files: rw-r-----
Hosted sites "files" directory: rwxrwx---
Hosted sites files under "files" directories: rw-rw----
Hosted sites subdirectories under "files" directories: rwxrwx---

Script based on guidelines given above

If you need to fix permissions repeatedly then the following script will help you, it is based on the guidelines given above and performs some checks before any modification to ensure it is not applied on files/directories outside your drupal installation.

#!/bin/bash

path=${1%/}
user=${2}
group="www-data"
help="\nHelp: This script is used to fix permissions of a drupal installation\nyou need to provide the following arguments:\n\t 1) Path to your drupal installation\n\t 2) Username of the user that you want to give files/directories ownership\nNote: \"www-data\" (apache default) is assumed as the group the server is belonging to, if this is different you need to modify it manually by editing this script\n\nUsage: (sudo) bash ${0##*/} drupal_path user_name\n"

if [ -z "${path}" ] || [ ! -d "${path}/sites" ] || [ ! -f "${path}/modules/system/system.module" ]; then
echo "Please provide a valid drupal path"
echo -e $help
exit
fi

if [ -z "${user}" ] || [ "`id -un ${user} 2> /dev/null`" != "${user}" ]; then
echo "Please provide a valid user"
echo -e $help
exit
fi

cd $path;

echo -e "Changing ownership of all contents of \"${path}\" :\n user => \"${user}\" \t group => \"${group}\"\n"
chown -R ${user}:${group} .
echo "Changing permissions of all directories inside \"${path}\" to \"750\"..."
find . -type d -exec chmod u=rwx,g=rx,o= {} \;
echo -e "Changing permissions of all files inside \"${path}\" to \"640\"...\n"
find . -type f -exec chmod u=rw,g=r,o= {} \;

cd $path/sites;

echo "Changing permissions of \"files\" directories in \"${path}/sites\" to \"770\"..."
find . -type d -name files -exec chmod ug=rwx,o= '{}' \;
echo "Changing permissions of all files inside all \"files\" directories in \"${path}/sites\" to \"660\"..."
find . -name files -type d -exec find '{}' -type f \; | while read FILE; do chmod ug=rw,o= "$FILE"; done
echo "Changing permissions of all directories inside all \"files\" directories in \"${path}/sites\" to \"770\"..."
find . -name files -type d -exec find '{}' -type d \; | while read DIR; do chmod ug=rwx,o= "$DIR"; done

Copy the code above to a file, name it "fix-permissions.sh" and run it as follows:
sudo bash fix-permissions.sh your/drupal/path your_user_name

Note: The server group name is assumed "www-data", if it differs modify it in the script code

Comments

re: find . -type d -name

re: find . -type d -name files -exec chmod ug+rwx,o-rwx {} \;

This only works for a new site (e.g. one that doesn't already have files in the /sites/[site]/files directory).
For the hardening of an existing site,`find . -type f -exec chmod u+r-wx,g+rw-x,o-rwx {} \;` sets all of the files inside sites/[site]/files to be read-only, and `find . -type d -name files -exec chmod ug+rwx,o-rwx {} \;` will only affect new files; anything currently existing in the /files folder will still be read-only. A `chmod -R ug+rwx,o-rwx /[path to site]/files/*` should fix this.

Thanks for the howto.

chmod -R ug+rwx,o-rwx /[path to site]/files/*

This command gives execute permissions for both the owner and group to all regular files residing within the /[path to site]/files/* tree? Isn't this a bad thing?

No

It's nuts that web server should own the site. In all normal cases your regular user (that you do your regular ssh, scp or ftp access with) should should own the installation files.

Anyway, this regular user should normally own an html area exclusively, from which the web server serves the pages of the host/virtualhost, that is only readable and searchable to others (i.e. the web server). After ensuring that this is the case the user then normally copies or uploads the contents of the distribution into the html area, thus maintaining ownership and sane permissions. The user then grant the web server read, write and search permission to the files directory of the site by changing the group access. Optionally, the user also gives up his own write permissions for the files directory (in order not to tamper recklessly with this area as it should be managed exclusively by the web server).

There's really no need for recipes, if the user doesn't grasp this he simply needs to do UNIX permission homework or else he'll never be secure. If that is the case, enter the following into shell or Google:

man chown
man chgrp
man chmod

Thanks for the advice. After

Thanks for the advice. After reading your post, I found the following relevant information:
http://www.onlamp.com/pub/a/apache/2004/05/28/apacheckbk.html

"Apache runs as the user specified in the User directive. Files need to be readable by that user. Directories need to be +x (searchable) by that user. CGI programs need to be runnable (+x) by that user."

A question

User apache is completely unpriviledged and has no login shell. A question, supposing that the file index.php in drupal's root have these file permissions: -r--r----- 1 apache apache 980 Mai 18 15:25 index.php. Would it be possible to an attacker explore an Apache vunerability to take advantage of the ownership by apache to execute a chmod on it and alter the permission in a way that it becomes writeable and then modify or overwrite it uploading a hacked one?

Shell or no shell

Shell or no shell, as long as the user the server and the php scripts runs as owns files and directories, it can also alter them. Owning files is a privilege. So if your server, or php, or Drupal has a hole, or most likely, if you accidentally allow someone to plant some php code, you're in trouble.

$ ls -l secretfile
---------- 1 www-data www-data 0 2009-08-20 21:10 secretfile
$ wget http://localhost/malign.php > /dev/null 2>&1
$ ls -l secretfile
-rwxrwxrwx 1 www-data www-data 0 2009-08-20 21:10 secretfile

Understood

Thank you for your clarification, when you told about this on the comment I became worried because I didn't think of this possibility. Now that you explained how it can be achieved I saw the problem and modified all my permissions in the server to u=rwx,g=rx,o= for directories and u=rw,g=r,o= for files and the ownership is site_owner:apache. This way only site_owner can chmod the files and directories.

doesn't work

Hi, permissions above look pretty tight. However it doesn't work ... at least for me (Ubuntu 8.04 x64 serv), I don't know which files have to be writable, executable etc ... but with these permissions I am getting only "Forbidden - u don't have permissions ....." to whole drupal subdirectory, when I set drupal directories to "chmod 1755" and files "chmod 1644" it's much better (perhaps sticky bit is not necessary), i can work in any case at it's very important for me (newbie in drupal). I would like to have secure site at the same time, therefore I tried permissions here from "wiki", i have experimented with them about 2 hours and ended up with working ones as I mentioned above. I haven't tried to edit .htaccess, perhaps there is also some possiblility to achieve usefull behavior.

----edit-----
as mike_waters points out directories need to be executable (x) so one has to # find . -type d -exec chmod u=rwx,g=rx,o=x {} \; this fix the problem, I should have read carefully his post. It could save me 3 hours of trying and googling ...

Everything is right on this post

If you have read those 3 commands on the beginning of this howto carefuly you should have seen that for directories it has an x to permit access.

[root@localhost]cd /path_to_drupal_installation
[root@localhost]chown -R greg:www-data .
[root@localhost]find . -type d -exec chmod u=rwx,g=rx,o= {} \;
[root@localhost]find . -type f -exec chmod u=rw,g=r,o= {} \;

I needed to modify thos

I needed to modify thos commands to
find . -type d -exec chmod u=rwx,g=rx,o=rx {} \; - that's 755
find . -type f -exec chmod u=rw,g=r,o=r {} \; - that's 644

Otherwise my Bluehost hosted Drupal site shows Forbidden when I try to access it.

--------------------------
Drupal projects:
http://MalinaMusic.ru
http://ephototips.com

Other prijects:
http://malina.mobi

I also had to modify the permissions

I am using Hostgator and the documented code broke my site. Being a newbie I panicked because I didn't know what files and folders I just changed. Luckily, I found this post and was back up and running.

It is important to note that I could not execute the first line:
chown -R greg:www-data .

I omitted it when after realizing that chown was not permitted and gave me an invalid user error. Perhaps this is part of my problem.

Small side note, I experimented with:
find . -type d -exec chmod u=rwx,g=rx,o=r {} \;

and my site still worked but had no styling. I suppose there is a use for that down the road.

Hey, it's wrong giving to

Hey, it's wrong giving to others any kind of permission and the user greg, if you read carefully, was used as an example and you MUST change it for the proper user that administrates Drupal(usually root or your user). Look at this: "To set the permissions all at once you can issue these commands from the Drupal root directory. I'm assuming that greg user is part of greg group and that greg is the site owner." It´s just an assumption just to explain a situation not an obligation. READ CAREFULLY AND REPEAT THE STEPS, YOU SURELY MISSED SOME STEP!

This documentation is for site administrators, newbies must know deeply about Linux permissions scheme before using this guide.

Big thanks!

I followed the instruction above and the entire site broke. I was having problems with a theme, thought I should go ahead and verify permissions across the entire site. Running your permissions got my site working again.

The only thing worse than no documentation is documentation that doesn't work.

Hey, it's wrong giving to

Hey, it's wrong giving to others any kind of permission and the user greg, if you read carefully, was used as an example and you MUST change it for the proper user that administrates Drupal(usually root or your user). Look at this: "To set the permissions all at once you can issue these commands from the Drupal root directory. I'm assuming that greg user is part of greg group and that greg is the site owner." It´s just an assumption just to explain a situation not an obligation. READ CAREFULLY AND REPEAT THE STEPS, YOU SURELY MISSED SOME STEP!

This documentation is for site administrators, newbies must know deeply about Linux permissions scheme before using this guide.

ACL Support

ACLs are an under-used feature of Linux. It's great for web development, as the server can have one set of permissions while the developers have their own. However, I don't think Drupal supports this, because it thinks that the server has write permissions to a directory that it doesn't have write permissions to.

Being brand new to Drupal, I could be wrong, but I believe I'm interpreting the example below correctly.

Status Report:
Configuration file Not protected
The directory sites/default is not protected from modifications and poses a security risk. You must change the directory's permissions to be non-writable.

Directory Permissions:
elizabeth:/home/www/faba3.v.cryptomeme.com/webroot/sites$ ll
total 8.0K
drwxrwx---+ 2 elizabeth staff 4.0K 2009-09-16 12:40 all
drwxrwx---+ 3 elizabeth staff 4.0K 2009-11-17 15:27 default

elizabeth:/home/www/faba3.v.cryptomeme.com/webroot/sites$ getfacl default/
# file: default/
# owner: elizabeth
# group: staff
user::rwx
group::rwx
group:www-data:r-x
mask::rwx
other::---
default:user::rwx
default:group::rwx
default:group:www-data:r-x
default:mask::rwx
default:other::---

elizabeth:/home/www/webroot/sites/default$ ll
total 28K
-rw-rw----+ 1 elizabeth elizabeth 9.3K 2009-11-17 15:27 default.settings.php
drwxrwx---+ 2 elizabeth staff     4.0K 2009-11-17 15:26 files
-r--r-----+ 1 elizabeth staff     9.3K 2009-11-17 15:27 settings.php

elizabeth:/home/www/webroot/sites/default$ getfacl files/
# file: files/
# owner: elizabeth
# group: staff
user::rwx
group::rwx
group:www-data:r-x
mask::rwx
other::---
default:user::rwx
default:group::rwx
default:group:www-data:r-x
default:mask::rwx
default:other::---

Securing the files directory permissions properly

Now for the "files" directories the permissions are slightly different because it must have write permission to the www-data group too [run the following from the Drupal root folder]:
find . -type d -name files -exec chmod ug=rwx,o= {} \;

This command is not so secure because some contrib modules contain 'files' directories such as feedapi, and in core we now have ./modules/simpletest/files

Also, it does not cover the case where you have existing files in it the 'files' directory. I can't find a better way other than running the following commands from each sites/SITENAME/files directory:

cd /sites/SITENAME/files
find . -type d -exec chmod ug=rwx,o= {} \;
find . -type f -exec chmod ug=rw,o= {} \;

I'm happy to update the documentation with this, but maybe someone has a better way of doing this?

Updated handbook to make this command better

I agree with what you told, but when I wrote this howto I didn't know a better way of doing this. Later I wrote a bash script to automate the process of setting permissions according with this handbook and it worked like a charm but I forgot to update the handbook. Now the command is there and it takes into account that there files already residing inside each "files" directories found.

Is there a permanent solution?

Thank you for the guide, it works perfectly! However, if I create a new Imagecache preset, or automatically create a new sub-theme with Zenophile, the owner of folder and files is set to www-data...

Do I need to run the commands again to reclaim ownership and set read/write permissions, or is there a more permanent solution?

iterating through sites

Why not to do something like this:

for d in sites/*/files; do
  find $d -type d -exec chmod ug=rwx,o= {} \;
  find $d -type f -exec chmod ug=rw,o= {} \;
done

numeric values

Many of us work through FTP programs, and not the command line.

Could you please post info on the numeric values corresponding to the CHMOD equivalents you listed here?

Thanks!

Summary of permissions and numeric values

Like two_wheeler, I need to use the numeric values.

As I read (and re-read) the instructions in this document under Linux servers, and combine that with the information from Mike_Waters, I think this is what they mean.

For all directories and subdirectories in Drupal's root directory:
Symbolic notation: rwxr-xr-x
Octal numbers: 755
Which means:
  • Owner: read, write, execute
  • Group: read, execute
  • Others: read, execute
For all files inside Drupal's directories:
Symbolic notation: rw-r--r--
Octal numbers: 644
Which means:
  • Owner: read, write
  • Group: read
  • Others: read
For the "files" directory inside Drupal's "sites" directory:
Path: /sites/files or /sites/default/files
Symbolic notation: rwxrwxr-x
Octal numbers: 775
Which means:
  • Owner: read, write, execute
  • Group: read, write, execute
  • Others: read, execute
For all files inside Drupal's "files" directory and inside any subdirectories with the "files" directory
Path: /sites/files/*.html and all other files in files directory
Path: /sites/files/subdirectories/*.html and all other files in subdirectories
Symbolic notation: rw-rw-r--
Octal numbers: 664
Which means:
  • Owner: read, write
  • Group: read, write
  • Others: read

If someone in-the-know could confirm or correct this it would be a big help.

Thanks!

The handbook has been updated

The handbook has been updated and I put a session explaining the chmod non numeric permission representation. If you carefully read the results of each command you'll see that others has no access at all to any file or directory contained in Drupal's installation directory and all the directory tree below it, all the other permissions you wrote are correct. If you write the commands suggested in this handbook, you'll have the best configuration for security. You can simply copy and paste them since you are inside drupal's root directory, if you are not, you'll mess all your filesystem permissions!

file write permissions

Great explanation of this confusing stuff, but please explain - is it necessary for any user (including the web server user) to have write permission on any files in the drupal directory at all?
I think the only necessary write permission is on the files directory and subdirectories, but not on files within these directories - is this wrong?
Similarly all directories should have execute permission for the web server and no files should have execute permission at all.
Then if you want to edit some files the write permission on those files, and the execute permission on the directory they are in, can be given
to the owner (and never the web server.)

Yes it's wrong, you MUST give

Yes it's wrong, you MUST give to all files write permission by the webserver because if you don't, Drupal will not delete files from your filesystem when you delete it from a Drupal post. Only the file reference will be removed from the post leaving the file untouched on the filesystem. Simply trust on what is explained on this handbook and make it the way it's written here. It will be all right!

Um, no. Only the

Um, no. Only the sites/.../files directory (and mayeb images) need to be writable by the webserver. Any other file or directory that is writeable by your webserver is a security risk.

File Permissions

Can you please respond to the thread link below found in this handbook here as we are using FTP and are newbies.

I am so confused because these settings being posted are already defaulted and the Module you suggested is giving me a LOT of file permission issues and I have no idea what to change them to.

http://drupal.org/node/244924#comment-4519336

Thank you lsrzj for your time and support

why cannot have this permission

with folder files/images;
If I set rwxrwxr-x and owner root I cannot upload images
# Directory "iimages" is not accessible under file system!
# Unable to get a working directory for the file browser

If I set rwxrwxrwx and owner root I can upload images
but the module alert that
Some files and directories in your install are writable by the server

If I set rwx------ and owner apache I can upload Image but always same alert's message

why cannot use this
rwxrwxr-x owner root ?

os centos and imce with fckeditor

other:
Security Review also alert regard html full, which html tags is preferable to remove from html full?

server does not run as root

Usually, server run as user www-data or nobody. So if you have your files owned by root, only if "others" with the relevant permissions will be accessing them. Check owner and groups in the "Configuration examples" at the beginning of this post.

files directory permissions for CentOS

on CentOS (which many cPanel servers use), cd to the public_html directory if necessary, then:

chown -R nobody:nobody /sites/default/files

This will make the apache web server able to upload images including with ckeditor/imce

Just figured this out after a day of struggles hope it helps someone.

http://ade.pt
strategies ~ systems ~ support

Thanks for writing this and

Thanks for writing this and everything, but all that I and 99% of people reading this page really want is a list of numbers next to a list of folders. This just confuses me and makes something really simple into a frustrating and confusing waste of time. Here is the permissions you should set for folders in Drupal 6.x, for those who don't feel like learning apache command line scripting just to set some permissions:

/default on 755
/default/files including all subfolders and files on 744 (or 755)
/default/themes including all subfolders and files on 755
/default/modules including all subfolders and files on 755
/default/settings.php and /default/default.settings.php on 444

Works, tnx

By the way Jason, I followed your indications (thank you!) and it worked :)

I started with Drupal in 2007 and then my life got stuck...

A Big Thank You!

I can't begin to tell you how quickly you resolved my can't write to files directory problem after migration with these simple cut and paste instructions:

[root@localhost]cd /path_to_drupal_installation/sites
[root@localhost]find . -type d -name files -exec chmod ug=rwx,o= '{}' \;
[root@localhost]find . -name files -type d -exec find '{}' -type f \; | while read FILE; do chmod ug=rw,o= "$FILE"; done
[root@localhost]find . -name files -type d -exec find '{}' -type d \; | while read DIR; do chmod ug=rwx,o= "$DIR"; done

Since our community has thousands and thousands of image files, what a time saver! This information helped me understand how to more tightly reign in permissions on files and saved the day for me.

A big thank you.

protoplasm

little bit safer

First of all: thanks for this doc, it's an important part of drupal's usage.

The 1st sentence is the heart of the matter: "system should be configured so that the webserver does not have permission to edit or write the files which it then executes".

'files' directory is an exception, that's why it is a security risk.
If someone can upload script (php) into that folder, your server is broken.

Let's minimize this case:
1.
files/.htaccess should not be writeable by webserver

2.
disable php in that folder, add this line to your files/.htaccess:

AddHandler default-handler php

(Your server will be safer, if a security hole or a weak admin password allows to upload php files.)

A great idea, but if you

A great idea, but if you grant write permission to the "files" directory itself, that permission could be used to overwrite any .htaccess file within, regardless of the permissions on that file (at least on some OSes). So to really accomplish this, you'll need to put the directives into your main Apache site config. Something like this:

<Directory /var/www/pathtositeroot/files>
  SetHandler default-handler
  Options None
  AllowOverride None
</Directory>

Still Confused

I have some of my sites that have user and group set to apache for everything / all files and dirs. Is this bad? Under the impression that user apache is a special user with very limited permissions.

Also I run my own server so don't need a user for each site I host so I assume if I need to have the user not be apache I can just create a user eg webdude and use them for all my sites or is this less secure?

You must create it and you

You must create it and you must use this user. If a user is the file and directory onwer all limitations go to the ground. You simply can put an script to change permissions and ownerships as you want, hackers will do it undoubtedly

Audit what is currently writable

From a serverfault thread
To see if your webserver can write to anything that it's not supposed to, if you have sudo, you can run

sudo -u www-data find . -type f -writable | grep -v sites/default/files

- this will list anything writable by the apache user - it should be empty after your site files dir is excluded.
It will just list, not fix it for you (the commands in the OP will do that for you).

centos find command

on centos would that be: sudo -u apache find . -type d -perm /u=w | grep -v sites/default/files ?

Joel Box - Mondial-IT

In summary...using FTP for file permissioning

Hi lsrzj, would you please confirm my translation of your documentation and your script per below:

I need to use the numeric values to apply permissions via FTP for a site hosted on Bluehost.

I reviewed the security script suggested in the document, under the heading: "Script based on guidelines given above". I am yet to test this but I believe it means:


1. [@ ROOT] DRUPAL CORE PLUS OUR ADDED MODULES & THEMES

  • All Core Drupal Folders and Sub-Folders = 750 (rwx,r-x,---)
  • All Core Drupal Files and Files in subfolders = 640 (rw-,r--,---)
  • Our own modules/themes/libraries use the same lockdown permissions.
  • /sites/all/themes = as above
  • /sites/all/modules = as above
  • /sites/all/libraries = as above



2. [@ /SITES] DRUPAL SETTINGS

  • /sites/default Folder = 755 (rwx,r-x,r-x). Personally I think this should be = 750 (rwx,r-x,--) if it works.
  • /sites/default/settings.php = 444 (r--,r--,r--). Personally, I think this should be = 440 (r--,r--,---) if it works?



3. [@ /SITES/.../FILES] WRITEABLE FILES in /sites/all/default/files folders : (like images, file attachments etc)

  • All Folders in /sites/all/default/files and all its subfolders : 770 (rwx,rwx,---)
  • All Files in /sites/all/default/files and it subfolder files : 660 (rw-,rw-,---)

these folders/files are the exception so that Drupal can delete the files attached to posts when they are deleted etc.



4. REDUCING WRITABLE FILES VULNERABILITY
Addtitional recommendation by: herend on February 24, 2011 at 11:57am
"...system should be configured so that the webserver does not have permission to edit or write the files which it then executes". So the server will be safer, if a security hole or a weak admin password allows to upload php files.

1. files/.htaccess should not be writeable by webserver
2. disable php in that folder, add this line to your files/.htaccess:
AddHandler default-handler php



I hope this is a correct translation and likely to work! I will investigate and attempt. Any confirmation from lsrzj or others, that this looks sensible, would be appreciated.

4. REDUCING WRITABLE FILES VULNERABILITY

hi,
what is best chmod for `files/.htaccess` ? can set 444?
"1. files/.htaccess should not be writeable by webserver"

i add below lines to my files/.htaccess:

RemoveHandler .php .phtml .php3
RemoveType .php .phtml .php3
php_flag engine off

is this secure?
no problem?

please help
thanks

I have a test site setup automatically with user=me group=me. How is www-data not even factored into this and the site works just fine. According to this tutorial. apache needs to have at least read access to the files but the www-data group/user has no permissions. Only my user/owner has permissions.

All I did was download drupal and extract it and the site works fine. Working with all the permission setting above gives me all types of problems. Such as the login page not being responsive.

On a traditional system...

There are at least *three* pseudo-groups that have their own permission set. 'owner', 'group', and 'other'
It would be normal for a host that set your user up with a web directory to assume that you wanted stuff you put there to be world-readable, so the 'other' permissions probably include the normal 'read-only' permissions, and www-data can read and serve your files.

There are now a number of extended file system properties that allow even more control than that, but in this case, they are probably not an issue.

Help to harden drupal

I went into the drupal site i have just built and used the module security review and it says
all the files inside the following directories (includes,modules,sites,misc,themes) can be written to by the webserver.Also other files such as profiles , changelog. On top of that, I went into the user pane in phpmyadmin and i did find three users who i had no idea of ever registering(some really strange gmail email adresses)I am the only person who has access to the site.I have no knowledge of php and was wondering what would be the simplest way of how to correct this?(is permissions via filezilla a viable option?)Also the hosting has register_globals on. I did seem to fix that with a php.ini file which had the term "register_globals = off"is that a good idea.The hosting provider is machighway, any ideas?what is the best secure ftp program for a mac?
Thanks.

And the right way for the Linux?

I wonder why there were no a single word about Linux ACLs while they do really good job.
Recently I was trying to setup permissions/owns for a website to provide access to another developer and faced the fact that technically it is impossible to achieve the result that would secure enought and flexible using old-style linux fs security. I will demonstrate what I mean.

Suppose we have next setup:

Users:
customer - site's owner
dev1, dev2 - two developers
apache - apache user

Reqs:
1) customer, dev1, dev2 - should have r/w access to the site
2) apache - should have r/w access to the site's /sites/all/files dir only
3) any changes to site's files shouldn't break the requirement 1-2. For example, files created by apche should be r/w accessible to customer, dev1 and dev2 and vice versa.
4) nobody else should have access to the site

I'm gonna skip considering different "tranidional" approaches to achieve above, including running patched apache which can set specific owner/owning group (vie AssignUserID for example), for only reason - it would be either impossible or ugly to the extreme.

Now I'll show how to do this with simple native Linux ACLs. Let us assume the site root is under 'www' dir of the current directory and all the files are owned by the `customer` user and the `customer` group.

1) adding customer user and group to the "write list" for all the files:

setfacl -R -m user:customer:rwx, group:customer:rwx www
setfacl -R -d -m user:customer:rwx, group:customer:rwx www (-d stands for default perms - i.e. inherited)

2) adding dev1 and dev2 to the "write list" for all the files:

setfacl -R -m user:dev1:rwx, user:dev2:rwx www
setfacl -R -d -m user:dev1:rwx, user:dev2:rwx www

3) adding apache user to the "write list" for sites/default/files:

setfacl -R -m user:apache:rwx www/sites/default/files
setfacl -R -d -m user:apache:rwx www/sites/default/files

That's all. Note - not a single chmod/chown issued. Let us see file permissions now with example output from real setup (customer = mosaicum, dev1 = fantomas, dev2 = doka, apache as is):

-bash-3.2$ getfacl www
# file: www
# owner: mosaicum
# group: mosaicum
user::rwx
user:fantomas:rwx
user:doka:rwx
group::r-x
mask::rwx
other::--x
default:user::rwx
default:user:fantomas:rwx
default:user:doka:rwx
default:user:mosaicum:rwx
default:group::r-x
default:group:mosaicum:rwx
default:mask::rwx
default:other::--x

-bash-3.2$ getfacl www/sites/default/files
# file: www/sites/default/files
# owner: root
# group: root
user::rwx
user:apache:rwx
user:fantomas:rwx
user:doka:rwx
user:mosaicum:rwx
group::r-x
group:mosaicum:rwx
mask::rwx
other::--x
default:user::rwx
default:user:apache:rwx
default:user:fantomas:rwx
default:user:doka:rwx
default:user:mosaicum:rwx
default:group::r-x
default:group:apache:r-x
default:group:mosaicum:rwx
default:mask::rwx
default:other::--x

Advantages:

1) You don't need chmod/chown. You don't even need chmod g+s'ing
2) You don't need to reissue commands (if only some outdated software which doesn't respect ACLs will break them) - acls are inherited (thanks to "-d")
3) You ain't depending on who creates files no more - you just don't care about owners - and they now go like the should - preserving names. So for example if it was you, who last uploaded a new version of a file - then it will be owned by you and your group, but the staff don't lose control over it.

UPDATE:

* drush dl breaks ACLs since it moves (renames) downloaded and extracted files from /tmp to the site's dir (and while moving ACLs/owners/permissions never copied - this is "by design").
But thanks to drush developers, shell's rename is inside drush_move_dir() which has a workaround in case when system rename "doesn't work": files from /tmp are first copied to the site's dir and then unlinked from /tmp. When acting like this, ACLs are applied/preserved. To make system rename doesn't work you just add one line to either /etc/drush/php.ini or ~/.drush/php.ini:

disable_functions = rename

* tar zxf module.tar.gz would likely extract module which will become r/o for all the groups and named users. I think this is because tar preserves r/o for groups permission when creating archive and when extracting, this changes "mask" attribute of extended ACL to become "r-x" and not "rwx".

Well, I didn't find how to make tar to extract ignoring mode (or rather with mode changed to 666). But to change the mask back you can either use setfacl again, or just issue this right after tar zxf:

chmod -R g+w module

Is greg a member of www-data?

When I setup my drupal with greg:www-data and they're not a member of each other, it breaks w/ permission denied. Did I misread the above? It's not explicit if greg is or isn't part of www-data or vice versa. I'm guess mine's not setup right...

As per my edit note. the first code box shows "files/" with owner as www-data:greg... but the script at the bottom doesn't chown the "files/" directory to $group:$user. This differs from what is said in the first section.

Also can someone intelligently(ie s.w.i.m.) comment about setting the SGID, chmod g+s, to "files/" to keep the group each time www-data creates a file. So that each file is created as www-data:greg (vs www-data:www-data). Does it help?

This was my home setup for a

This was my home setup for a long time (except I will use `greg` as the username) :

sudo chown -R greg:www-data www

sudo chmod -R g-w www # r/o for www-data
sudo chmod -R g+w www/sites/default/files # r/w for www-data
sudo chmod -R g+s www # keep group inheritance

gpasswd -a greg www-data #so you can write where www-data can write

Also, take a look at my previous comment - about ACLs. I'm upgrading whole my home web server to ACLs now...

I'm quite confused by this

I'm quite confused by this post. I am tying to set permissions on my site and using filezilla I can change the numeric value. I don't know (shared hosting) if I can run any scripts which will set all the appropriate permissions for me? I have access to my cPanel with file manager etc. but not to the server.

I can't find a simple list anywhere of the values needed for each of the folders/files so this is making setting permissions a nightmare. I have gone from local to live and now have a site (in maintenance mode) which really needs security tightening up.

If anyone has a link that I have missed to a simple explanation ie

includes & subfolders: 755
files in includes & subfolders: 644

I don't understand what this apache username is? Does that apply to me on shared hosting?

Or something.

Oh, shared... my condolences,

Oh, shared... my condolences, comrade. And I know this is not what you asked about, but... upgrade your hosting. At least you simply must get working Unix shell.

As for what you may do (apart from upgrading hosting) - contact sysadmins and ask them how your apache runs. It may even launched under your user, thus having full access to all the files.

lol, I'll send you my email

lol, I'll send you my email and you fill out the paypal form then!

I have to make do with what I have and sadly that means... filezilla. Sad but true. My host wont let me set 444 for settings.php through filezilla so I had to do that one in the control panel.

I read in another post that NOTHING needs write permissions other than files folder. There's loads of conflicting posts. Going from local to live has taken me the best part of 2 days, first time for everything though, It'll get easier.

Group memberships..

Great page but perhaps needs to make mention of the fact that any files uploaded will be owned by www-data:www-data..

Only ways I know of to get around this are..

1. Add the user to the www-data group - Problem here is that the user then has access to everything that www-data has access to potentially including other users files (if you have more than one user/site on the server.. If its a single site server this isn't such an issue)..

2. Set the UID on the writeable directories so that newly created files inherit the user..

3. Create a separate group and make www-data and the user members of the group.. Use this new group when setting permissions and set the GID of the writeable directories to the new common group..

Not sure which way is best or most secure but think that whichever is felt to be best is detailed on the page..

suPHP

Hmm

Can anyone help me work out the correct settings for a suPHP environment. Many shared hosts will run as suPHP, which means a script runs with its owner's permission.

That means that any PHP files in the Drupal core / contrib folders will need to be not-writeable by the file's owner. But, because Drupal is running under the owner of the file-hierarchy, the Updates module will not ask for any alternative credentials when processing an update, and will simply fail (the folder it wishes to update is not writeable).

I'm trying to work out what the optimal solution is, so if anyone could help...