1. Introduction

Some directories in Linux are accessible by everyone, i.e., all security principals or, put simply, the world. This means such directories provide at least read permissions globally. However, it’s usually much rare to see a world-writable object, let alone a whole directory. Yet, there are such cases.

In this tutorial, we’ll go over the default world-writable directories of a fresh Linux system and the concept of fully-open permissions in general. First, we discuss the common standard of the Linux base directory structure. Next, we explore the default permissions for most of that top-level hierarchy. After that, we talk about the security of world-writable directories. Later, we enumerate default Linux paths with fully-open permissions. Finally, we check ways to find and identify all such directories.

For brevity, we use the terms world-writable and fully open more or less interchangeably.

We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4. It should work in most POSIX-compliant environments unless otherwise specified.

2. Filesystem Hierarchy Standard (FHS)

Linux follows the UNIX Filesystem Hierarchy Standard (FHS). Among others, the standard defines areas of the rootfs root filesystem, so users and applications can predict the correct location of given files and directories:

+-----------------------------------------------------------+
| Directory | Description                                   |
|-----------+-----------------------------------------------|
|       bin | essential command binaries                    |
|      boot | boot loader static files                      |
|       dev | device files                                  |
|       etc | host-specific system configuration            |
|       lib | essential shared libraries and kernel modules |
|     media | mount point for removable media               |
|       mnt | mount point for temporarily filesystem mounts |
|       opt | add-on application software packages          |
|      sbin | essential system binaries                     |
|       srv | data for provided services                    |
|       tmp | temporary files                               |
|       usr | secondary hierarchy                           |
|       var | variable data                                 |
+-----------------------------------------------------------+

Notably, some of these directories, like /media, /mnt, srv, and /usr, can include a further subhierarchy. However, that may not comply with any FHS guidelines.

Still, there are FHS recommendations for the top-level or root paths. For instance, /bin and /sbin utilities usually contain specific executables.

Of course, this means they should be accessible to most users and have the proper permissions set.

3. FHS Permissions

In general, the permissions of top-level FHS directories stem from their function. Let’s explore the paths with ls and its [-l]ong listing and [-d]irectory flags:

$ ls -ld \
/bin /boot /dev /etc /lib \
/media /mnt /opt /sbin /srv \
/tmp /usr /var
lrwxrwxrwx   1 root root       7 Oct 10  2022 /bin -> usr/bin
drwxr-xr-x   3 root root    4096 Apr  4 11:10 /boot
drwxr-xr-x  16 root root    3330 Apr  4 11:11 /dev
drwxr-xr-x 115 root root   12222 May  5 15:15 /etc
lrwxrwxrwx   1 root root       7 Oct 10  2022 /lib -> usr/lib
drwxr-xr-x   3 root root    4096 Oct 10  2022 /media
drwxr-xr-x   6 root root 2660010 Apr 04 04:04 /mnt
drwxr-xr-x   2 root root    4096 Oct 10  2022 /opt
lrwxrwxrwx   1 root root       8 Oct 10  2022 /sbin -> usr/sbin
drwxr-xr-x   3 root root    4096 Mar  3 03:33 /srv
drwxrwxrwt  12 root root    1024 May  5 05:55 /tmp
drwxr-xr-x  14 root root    4096 Oct 10  2022 /usr
drwxr-xr-x  14 root root    4096 Apr  4 04:40 /var

As we can see, some of the above paths are links to /usr subdirectories. Since permissions of symbolic links don’t matter, we can resolve their targets:

$ ls -ld /usr/bin /usr/lib /usr/sbin
drwxr-xr-x  2 root root 55200 May  5 01:01 /usr/bin
drwxr-xr-x 78 root root  4096 Apr  4 02:20 /usr/lib
drwxr-xr-x  2 root root 20666 Apr  4 02:25 /usr/sbin

Evidently, all of this default structure is owned by root. Following the links, we can see most permissions are also the same: rwxr-xr-x. In other words, only the owner (root) can write to almost all root FHS directories.

Still, there are exceptions.

4. Security of World-Writable Paths

Since anyone can create files in fully-open directories, applications are mainly responsible for several points:

  • avoid overfilling the filesystem
  • securing own filesystem objects with the proper permissions
  • attempting filesystem object creation with overlapping names
  • executing foreign files

While overfilling can be limited to a partition created for a specific purpose, that’s not always the case. Further, file and directory creation is usually very important in this context. For example, we can use the open() system call with O_EXCL to ensure we don’t replace files. In specific instances, mktemp can also be helpful.

Still, we should definitely protect sensitive content from open permissions, as failing to do so can have severe consequences.

Finally, the sticky bit usually prevents the deletion of a world-writable directory and files within it with a few exceptions:

  • owner of the file
  • owner of the directory
  • root

Further, we can recognize this setting as a four-digit mode that starts with 1, e.g., 1666. When it comes to the output of ls, a t takes the place of the last executable bit character (normally x or ) to indicate the sticky bit.

For instance, a fully-open directory with the sticky bit would have drwxrwxrwt as the first column of ls in long list mode.

5. World-Writable FHS Paths

Although it’s relatively uncommon in general, some directories do have open permissions that allow everybody to write to them.

Still, the control over these exceptional paths is often limited because they usually have the sticky bit set.

5.1. Temporary Directories

As expected, the /tmp directory has a different set of permissions from the others at the root level:

$ ls -ld /tmp
drwxrwxrwt  12 root root    1024 May  5 05:55 /tmp

Naturally, the temporary directory has these rwxrwxrwt open permissions to serve all security principals. So, /tmp is world-writable. That means, by extension, /var/tmp and /usr/tmp may also have the same permissions:

$ ls -ld /var/tmp/
drwxrwxrwt 4 root root 4096 May  9 00:00 /var/tmp/

However, if they even exist, /var/tmp and /usr/tmp are sometimes only symbolic links to /tmp.

5.2. /dev/shm and /dev/mqueue

The /dev/shm directory can provide inter-process data sharing or fast storage for files that a reboot would delete:

$ ls -ld /dev/shm
drwxrwxrwt 2 root root 40 Apr 04 08:08 /dev/shm

Similarly, the /dev/mqueue POSIX message queue filesystem enables any principal to communicate with another:

$ ls -ld /dev/mqueue
drwxrwxrwt 2 root root 40 Apr 20 04:20 /dev/mqueue

As such, both /dev/shm and /dev/mqueue have world-writable permissions along with the sticky bit. In fact, we can see these as particular cases of a temporary directory.

5.3. Lock File Directories

Locks are files that ensure there is only a single instance of a given process. They usually reside in the /var/lock directory:

$ ls -ld /var/lock
lrwxrwxrwx 1 root root 9 Oct 10  2022 /var/lock -> /run/lock
$ ls -ld /run/lock
drwxrwxrwt 5 root root 100 Apr 04 14:00 /run/lock

Although it’s a symbolic link, following that reveals a lock directory, /run/lock in this case, with fully open permissions and the sticky bit set. Since locks are a common mechanism, these settings are to be expected. Again, this is also a specific-purpose temporary directory.

5.4. /var/* and /var/spool/*

Other temporary paths with a specific purpose include so-called spooler directories. They are mainly responsible for handling printing tasks but can also be used for mail and similar queues.

Since such activities are common among users and data only resides in the paths temporarily, spooler directories can be world-writable as well:

$ ls -ld /var/mail/
drwxrwsr-x 2 root mail 4096 Apr 16 10:17 /var/mail/
$ ls -ld /var/spool/
drwxr-xr-x 9 root root 4096 Apr  5 08:18 /var/spool/
$ ls -l /var/spool/
total 28
drwxr-xr-x 2 root        root        4096 Oct 10  2022 anacron
drwxr-xr-x 5 root        root        4096 Apr  4 18:18 cron
drwx--x--- 3 root        lp          4096 Jan 01 01:10 cups
[...]
lrwxrwxrwx 1 root        root           7 Oct 10  2022 mail -> ../mail
drwx------ 2 root        root        4096 May  5  2022 rsyslog
drwxrwxrwt 2 root        root        4096 Aug  8  2022 samba

However, even in this instance, the permissions are not open to the world for all except /var/spool/samba, which isn’t a default directory.

6. Identify World-Writable Paths

Although we can reference standards to recognize paths with open permissions, there are also other means to find them.

6.1. World-Writable Filesystems

Because they are part of the random access memory (RAM), tmpfs mounts are often globally accessible.

In fact, some of the directories we already saw are usually of this type:

$ df --output=source,fstype,target
Filesystem     Type     Mounted on
udev           devtmpfs /dev
tmpfs          tmpfs    /run
/dev/sda1      ext4     /
tmpfs          tmpfs    /dev/shm
tmpfs          tmpfs    /run/lock
/dev/sda2      ext4     /home
/dev/sda3      ext4     /tmp
/dev/sda4      ext4     /var
tmpfs          tmpfs    /run/user/1000

In this case, we see /run/lock and /dev/shm are both tmpfs and world-writable. However, /run doesn’t have open permissions despite being a RAM mount:

$ ls -ld /run
drwxr-xr-x 29 root root 920 May  5 06:56 /run

So, how do we definitively locate world-writable directories?

6.2. Find World-Writable Paths

Of course, outside of what the standards and logic point to, we can have many more world-writable paths. To discover them, we can use the POSIX find:

$ find / -maxdepth 3 -type d -perm -777
/var/tmp
/var/spool/samba
/run/lock
/dev/mqueue
/dev/shm
/tmp
[...]

Looking at a -maxdepth of 3 subdirectories under the / root mount point, we check for objects of the [d]irectory -type that have a [-perm]issions mode of 777. Of course, we can omit the -maxdepth parameter, switch the type to [-f]iles, change up the mode, or even prevent traversing other filesystems via xdev, depending on our needs.

7. Summary

In this article, we discussed fully-open directories in Linux, their behavior, and how to identify them.

In conclusion, although they are only useful in specific cases, world-writable directories exist, so knowing how and when to use them can be critical.