Permissions and ownership
When something cannot read a file, the internet says chmod 777. That makes the file writable by every process on the machine, including the compromised one.
The numbers
Three digits: owner, group, everyone. Read is 4, write 2, execute 1.
644— owner reads and writes, everyone else reads. Normal for files.755— the same plus execute. Normal for directories and programs.600— owner only. Keys, configuration with secrets.700— owner only, directory.
On a directory, execute means “may enter”, not “may run”. A directory with read but not execute lists names and lets you open nothing.
What a web application actually needs
Files owned by a deploy user, group owned by the web server's group, and the web server given read only:
chown -R deploy:www-data /srv/app
find /srv/app -type d -exec chmod 750 {} +
find /srv/app -type f -exec chmod 640 {} +
Then grant write access only where the application genuinely needs it — an
uploads directory, a cache directory — with 770 and nothing
else.
The application being unable to overwrite its own code is a feature. It is the difference between a web shell being uploaded and a web shell being uploaded and your source being rewritten.
umask
What permissions new files get. 022 gives 644 for files and 755 for
directories; 027 gives 640 and 750, keeping other users out
entirely.
Set it per service in the systemd unit with UMask=0027 rather than
globally, so one application's choices do not affect another's.
setgid for shared directories
chgrp -R developers /srv/project && chmod -R g+ws /srv/project
New files inherit the group instead of belonging to whoever created them. This is what makes a shared working directory actually work, rather than slowly accumulating files nobody else can edit.
ACLs for the awkward cases
When one more user needs access and you do not want a new group:
setfacl -m u:backup:rx /srv/app
And so that new files inherit it:
setfacl -d -m u:backup:rx /srv/app
getfacl /srv/app to read it back. A file with ACLs shows a
+ in ls -l, which is the clue when permissions look right
and behave oddly.
Finding problems
find / -xdev -type f -perm -002 2>/dev/null — world-writable
files, which should be almost none
find / -xdev -perm -4000 2>/dev/null — setuid binaries; know
what is on this list
namei -l /srv/app/data/file — permissions on every component of
the path, which is usually where the real problem is
See also users and sudo and knowing when a file changed.
Still stuck? Mail support@novogara.com — an engineer answers, at any hour. Back to the knowledge base