Skip to content

Users and Permissions

Linux, like Unix before it, has always been designed as a multi-user operating system. This means that it is primordial to understand how users and groups work, how permissions are managed, and how they affect what users can do, how they tie into Django and Python, etc.

Hopefully, this chapter will help clarify these concepts.

Users and groups

Users and groups are used to manage permissions. Every user is identified by a username, and every group is identified by a groupname. Each username is linked to a numeric user ID (uid), and each groupname is linked to a numeric group ID (gid). Each ID should only be used by one user or group. User and group names are only used for convenience, while most kernel functions rely on numeric IDs for authorization and access control.

By convention, regular users have IDs starting from 1000, while uids lesser than 1000 are restricted to system users. System users have no login, but can be used to run services like a database, web server, etc. Some common system users and groups could be www-data, http, or similar, depending on your distro and other factors.

Users belong to a primary group, but they can also belong to any number of supplemental groups which may provide them with extra permissions.

The root user

There is one special user, called root, which has a special uid and gid of 0. There is also typically a root group. This user is commonly called a superuser, as they have all permissions. It should not be used regularly, but it can be used to manage users, files, packages, etc. For security purposes, you should not run services as root.

Note that the root user is the only user that can run services on reserved ports, which is all ports below 1024. That means that it is common to start services as root, and configure them to drop privileges.

Dropping privileges

If you start a privileged process, specifically one with the CAP_SETUID capability, you can use a system call like setuid to change the user ID of the process after it has started. This is commonly used to start services as root so they can bind to restricted ports, then change to a user with lesser privileges. This helps increase security, since if there is some bug in some service, a hacker that exploits it could gain access to your server, but not as the root user. Of course, it is still bad, so make sure you update your servers regularly, and try to isolate services as much as possible.

One example of a program that works this way is nginx, which has a user username [group] option. nginx starts the master process as root, then uses username for worker processes. Depending on your distro, the username may be www-data or http.

Privilege escalation

As previously mentioned, you should generally avoid logging in as root, but rather you should escalate privileges from your regular user. You can do this using the sudo command (superuser do), or the su command (switch user).

For example, ls /root/ will likely give you a Permission denied error, while sudo ls /root/ will run the command as the root user which will have permissions to list the directory contents. It is common to use sudo to edit configuration files, manages users, install or update packages, etc. By default, sudo will run as the root user, but you may also run commands as a different user with sudo -u username command.

Privilege escalation attacks

Note that hackers or certain users may attempt to gain elevated privileges if they can access your system. Privilege escalation can be a good tool to manage your server, but you also want to ensure that permissions are restricted as much as possible.

Configuration files

The most common and important configuration files for user management include:

  • /etc/passwd: the user database file.
  • /etc/group: the group database file.
  • /etc/shadow: the secure user database file.
  • /etc/gshadow: the secure group database file.

The shadow and gshadow files are only accessible by processes running as the root user. The passwd and group files are readable by any user. The passwd file used to contain the password hashes for all users, which allowed other users to brute force passwords. For better security, hashed passwords are now kept in the shadow file.

Note that you should never edit those files directly, but you should rather use the commands which we will cover in a later chapter.

/etc/passwd/

The passwd file is a plain-text database containing the following colon (:) delimited fields:

username:password:uid:gid:gecos:homedir:shell

The username is the name the user uses to log in. It needs to be valid according to some rules. By convention, they are generally lower case. You can use your first name, first initial followed by your last name, first name followed by the first initial of your last name(s), etc.

As previously mentioned, storing the password hash in this file is insecure. Most modern Unix and Linux systems now use a placeholder like x to indicate that the password is set in the shadow file.

The uid is the numeric ID of the user. As mentioned, this should be equal or greater to 1000 for regular users. The gid is the numeric ID of the user's primary group.

The gecos field is an optional description of the user. It can contain their real name or contact information. It is named after the General Comprehensive Operating System.

The homedir is the user's home directory. It is usually /home/username for regular users.

The shell is the default command interpreter for this user. Some example values may be /bin/bash or /usr/bin/fish.

/etc/group/

The group file is a plain-text database containing the following colon (:) delimited fields:

groupname:grouppassword:gid:users

The groupname is the name of the group. Some groups may be predefined by the distro packagers.

The grouppassword is the password hash for the group. Like the passwd file, it is insecure to set in this file. Furthermore, group passwords may be insecure as they may be shared with multiple users. As such, we will not be using them.

The gid is the numeric ID for this group.

The users field is a comma-separated list of group member usernames. This typically does not list the user if the entry refers to their primary group.

/etc/shadow/

The shadow file is a plain-text database containing password information for all users. It contains the username, password hash, and password change policies. Please refer to the man page for more details.

/etc/gshadow/

The gshadow file contains the shadowed password information for all groups. It contains the group name, optional password hash if you want users to be able to gain permissions of a group they are not members of, a list of administrator usernames, and a list of member usernames.

File permissions

File permissions will be covered in the Linux File System Layout chapter.

Users and Python

You can access user and group information for the current user using the os module. Here are a few examples:

>>> import os
>>> os.getuid() # get the real UID for the current user
1000
>>> os.getgid() # get the real GID for the current user
1000
>>> os.geteuid() # get the effective UID for the current user
1000
>>> os.getegid() # get the effective GID for the current user
1000
>>> os.getgroups() # get the groups for the current user
[969, 998, 999, 1000]
>>> os.getlogin() # get the username for the current user
"username"

Here is one more example with dropping privileges. To do this, run Python as root with the sudo python command.

>>> import os
>>> os.getuid()
0
>>> os.setuid(1000) # change the uid for the process to 1000
>>> os.getuid() # we no longer have root privileges
1000