Linux users, groups and file permissions, the secure way
Two people needed to share a folder, the permissions got in the way, and someone typed chmod 777. It worked on the first try. So did the next person's attempt to delete everything in it.
The short answer
Give each person their own account, put people who share files in a group, and make the shared directory owned by that group with mode 2770 (setgid, no access for others). Add the sticky bit (3770) if members must not delete each other's files. Use an ACL for one extra reader. Never use 777.
On this page
What goes wrong
Linux decides access with three sets of bits on every file: one for the
owner, one for the file's group, and one for everyone else ("other"). Each
set has read (r), write (w) and execute (x). For a directory, w means
"may create, rename and delete entries", and x means "may enter".
chmod 777 sets all nine bits. On a directory, that means every account on
the host, including service accounts and a compromised web app, can create,
replace and delete files there. Deleting a file needs write access to the
directory, not to the file. So even files that are read-only for others can
be removed and replaced.
Shared accounts cause the second problem. When three people log in as
deploy, the logs cannot tell you who did what, and removing one person
means changing a password everyone knows.
What the docs say
For a directory, it indicates that BSD semantics are to be used for that directory: files created there inherit their group ID from the directory, not from the effective group ID of the creating process
Source: inode(7), The file type and mode
The sticky bit (S_ISVTX) on a directory means that a file in that directory can be renamed or deleted only by the owner of the file, by the owner of the directory, and by a privileged process.
Source: inode(7), The file type and mode
The ACL_MASK entry denotes the maximum access rights that can be granted by entries of type ACL_USER, ACL_GROUP_OBJ, or ACL_GROUP.
Source: acl(5)
The man pages describe each bit exactly, but they never put them together
into "how to share a folder". That missing recipe is why 777 is so common.
The secure configuration
# One account per person. Service accounts get no shell and no home.
useradd -m -s /bin/bash alice
useradd -m -s /bin/bash bob
useradd -r -s /usr/sbin/nologin -d /nonexistent app
# A group for the people who share files.
groupadd team-a
usermod -aG team-a alice
usermod -aG team-a bob
# The shared directory:
# 2 = setgid: new files get group team-a, not the creator's own group
# 7 = owner (root) full access
# 7 = group team-a may list, enter, create and delete
# 0 = everyone else: nothing
install -d -o root -g team-a -m 2770 /srv/team-a
# A drop directory where members may add files but not delete each other's:
# 3 = setgid + sticky bit
install -d -o root -g team-a -m 3770 /srv/team-a-drop
# One extra reader (the app service) without adding it to the group.
setfacl -m u:app:rx /srv/team-a
setfacl -m u:app:r /srv/team-a/report.txtMembers need a umask that keeps group write, such as 007, when they work in
the shared directory (umask 007 in their shell, or UMask=0007 for a
service). Group membership changes apply at the next login.
Prove it
The accounts:
getent passwd alice app | cut -d: -f1,3,4,6,7
id alice; id malloryalice:1000:1001:/home/alice:/bin/bash
app:999:999:/nonexistent:/usr/sbin/nologin
uid=1000(alice) gid=1001(alice) groups=1001(alice),1000(team-a)
uid=1002(mallory) gid=1003(mallory) groups=1003(mallory)The 777 directory. Alice writes a report; mallory cannot edit it, but can
delete it, because deleting is a write to the directory:
mkdir -p /srv/share-777 && chmod 777 /srv/share-777
su alice -c "echo q3 numbers > /srv/share-777/report.txt"
su mallory -c "echo tampered > /srv/share-777/report.txt; rm /srv/share-777/report.txt && echo mallory deleted the report"bash: line 1: /srv/share-777/report.txt: Permission denied
mallory deleted the reportThe group directory. New files get the team-a group from the setgid bit,
Bob can edit, Mallory cannot even read:
stat -c "%A %U:%G %n" /srv/team-a
su alice -c "umask 007; echo q3 numbers > /srv/team-a/report.txt"
stat -c "%A %U:%G %n" /srv/team-a/report.txt
su bob -c "cat /srv/team-a/report.txt; echo bob edit >> /srv/team-a/report.txt && echo bob can edit"
su mallory -c "cat /srv/team-a/report.txt"drwxrws--- root:team-a /srv/team-a
-rw-rw---- alice:team-a /srv/team-a/report.txt
q3 numbers
bob can edit
cat: /srv/team-a/report.txt: Permission deniedThe sticky bit stops Bob from deleting Alice's file in the drop directory:
su alice -c "umask 007; echo draft > /srv/team-a-drop/alice.txt"
su bob -c "rm -f /srv/team-a-drop/alice.txt"
stat -c "%A %n" /srv/team-a-droprm: cannot remove '/srv/team-a-drop/alice.txt': Operation not permitted
drwxrws--T /srv/team-a-dropOne ACL entry lets the app service read the report, and nobody else:
getfacl -p /srv/team-a/report.txt
su -s /bin/sh app -c "head -1 /srv/team-a/report.txt"# file: /srv/team-a/report.txt
# owner: alice
# group: team-a
user::rw-
user:app:r--
group::rw-
mask::rw-
other::---
q3 numbersThe audit: world-writable entries and files whose owner no longer exists:
find /srv -xdev \( -perm -0002 -a ! -type l \) -o \( -nouser -o -nogroup \)/srv/leftover
/srv/share-777The test script is secure-tests/linux-users-groups-file-permissions/run.sh.
Mistakes people make
chmod 777 to make an error go away
It fixes the error by giving the whole host write access. Find out which account needs which access, and give that one account or group exactly that.
Protecting the file but not the directory
A file with mode 644 in a 777 directory can be deleted and replaced by
anyone. Check the directory's mode as well as the file's.
Shared logins
sudo -u deploy for three people is still one identity in the logs. Give each
person an account and use groups and sudo rules for the shared parts.
Adding a service account to a people group
The service then gets everything the group can touch. Give it an ACL entry for the one file or directory it needs.
Forgetting to clean up after people leave
Files owned by a deleted user keep the old numeric ID. The next account that
gets that ID owns them. Find them with find / -xdev -nouser and reassign
them before you reuse IDs.
Checklist
- Every person has their own account; no shared logins.
- Service accounts have
/usr/sbin/nologinas shell. - Shared directories are group-owned with mode
2770, or3770with the sticky bit. - No directory outside
/tmpand/var/tmpis world-writable. find / -xdev -perm -0002 ! -type lhas been reviewed.find / -xdev -nouser -o -nogroupreturns nothing.- Extra readers use ACL entries, reviewed with
getfacl. - Group membership is reviewed when people change teams or leave.
Permissions are a conversation about who needs what. `777` ends that conversation by answering "everybody, everything", which is rarely what anyone meant.
FND
Learn it on a live range
Linux 1: the command line to a working, secure host, in Foundation: a real host in your browser, and every objective checked on the machine.
Start freeThe Secure Way
More on linux hosts
SSH, sudo, firewalls, mount options, updates and the host basics every engineer should get right.
All linux hosts guides