Exit the Past : Quit using "sudo su -"

Since the 70's Unix Operating Systems (O.S.) were designed to be multi-process and multi-user.

The root account is the account of the administrator so permissions and groups have been added to enable other users to perform administrative tasks.
If in the past root was only one person, systems often have many administrators nowadays, and working as root is discouraged in these cases.

Sadly even today most Administrators, Devops, Students do not have the proper training on how to leverage the native permissions capabilities of *Nix O.S. .
Therefore it's not rare to see terminals with the root # prompt.

Most of the time people use sudo su -, and that's funny, (and dangerous,) here is why.

Syntax error or logic flaw ?

-> man

su - run a command with substitute user and group ID
sudo — execute a command as another user

Which give us the following flow of execution.

sudo su -
# sudo : Become root 
# su   : Become root 
# -    : Start a login shell (aternatives : -l, --login)

"Start a login shell" WAIT WHAT !?

By using su/sudo you perform an authentication via the PAM
(Pluggable Authentication Modules for Linux)

pam_unix(su-l:session): session opened for user root(uid=0) by (uid=1000)

according to the man page, the -, -l, --login option
performs the following actions :

  • clears all the environment variables except TERM
  • initializes the environment variables HOME, SHELL, USER, LOGNAME, and PATH
  • changes to the target user's home directory
  • sets argv[0] of the shell to '-' in order to make the shell a login shell
    // According to /etc/passwd (very likely bash or sh).

You can verify the duplicate, useless elevation in /var/log/auth.log :

sudo: demo : TTY=pts/3 ; PWD=/home/demo ; USER=root ; COMMAND=/bin/su -
sudo: pam_unix(sudo:session): session opened for user root(uid=0) by (uid=1001)

su: (to root) root on pts/3
su: pam_unix(su-l:session): session opened for user root(uid=0) by (uid=0)

Same action then why two commands ?

The older one, su, is meant to change the user but to login you'll need the user's password.
And this can lead to a major issue : You have to share the account password, and if someone changes the password everyone else will lose access to the account.

/** Only root is allowed not to provide passwords when using su.
  * That explain why most users prefix the "su -" command with sudo.
  * It causes su to not ask the password of the root account. 

The more recent, sudo, is using an access list which determine which users and command you can use and have richer log.
By proving your identity with your password you are able to temporary run commands with another account.

/!\ Sharing root is discouraged /!\
Debian Administrator Handbook / Red Hat System Administrators Guide

-> Working with su -c "command" is quickly annoying because you have to type your password each time (this lead to the bad habit we have now).
To make it less inconvenient, sudo is designed to prompt for the password every 15min but you can tailor it in /etc/sudoers, see man sudoers for more details.

// It's also possible to configure sudo not to ask passwords.

No more double elevation : login shell with sudo

Most shells have an option to be launched as a login shell,
and if you don't know which, the man remains your best friend.
Bash uses the -l option :

# So easy
sudo bash -l

# On a target user ? no problem
sudo -u targetuser bash -l

But should I ?
Short answer : No.
Long answer : No you shouldn't.

  1. Sharing an account is a terrible idea.
  2. Loading environment variables is possible without changing your shell.**
  3. Playing with filesystem permissions enables to be in the needed groups.
  4. Writing scripts/automation avoids errors and the need of an interactive shell.

** : To load environment or other preferences to your current bash you can use the . or source commands with the relative or absolute path of the file as an argument.

$ . /home/youpi/.app_env_file 
$ # or
$ source /etc/environment

You can also have a look to man env. env can be used to define/change the environment for one command.

Problems with account sharing ?

Sharing any account is a bad idea because you'll break the O.S. design and part of its software.

To make the O.S. easier to use, over the years the shell did add more and more features: colors, keyboard arrows, pts, ...

As an example take bash, you can tailor it to your needs :

  • Environment
  • Aliases
  • Command History
  • ...

In your home directory you will find the files responsible for its behavior:

  • ~/.bash_profile : The personal initialization file, executed for login shells
  • ~/.bashrc : The individual per-interactive-shell startup file
  • ~/.bash_logout : The individual login shell cleanup file, executed when a login shell exits
  • ~/.inputrc : Individual readline initialization file
  • ~/bash_history : Individual command line history

Of course allowing people access to your account mean they can alter those files and change your precious settings or delete your history.

Additionally launching several parallel instances of bash will break history.
By default the process actually writes your history in the ~/.bash_history file at the end of the session.
So if you want to keep your history working and accurate, you must be the last one to close your bash instance, before your next session, not very convenient huh ?

Process isolation

In GNU/Linux, everything is a file.
Knowing that you know everything.

When you launch a process, it runs with your UID (by default).
You own the process, and every file in its /proc/PID/ folder.

To be able to work, the process must be able to read and write those files, this is done by inheriting your rights regarding file permissions.
This also prevents other (non-root) users to kill / modify your processes.

$ ps uw 104437
demo      104437  0.0  0.0   9644  3452 pts/2    T    19:52   0:00 top

$ ls -ld /proc/104437
dr-xr-xr-x 9 demo demo 0 15 nov.  19:52 /proc/104437

Sharing one account/UID means you enable people to mess with your stuff: file and processes.
Also working as root means you can accidentally break the system, impacting everyone.

Standard GNU/Linux ways to deal with users

By default when you install some packages such as apache2, ntpd, tcpdump.
The system creates an user and a group.

$ grep tcpdump /etc/passwd

As you can see it's voluntarily impossible to login with those services accounts.
Please note that some of them use /bin/false to achieve the same result less politely.

When you run tcpdump, apachectl, or services startup scripts for example, it silently changes the process owner in order to keep each application isolated from the rest of the system.

$ ps aux | grep tcpdump
tcpdump    16327  0.0  0.1  14964  7912 pts/1    S    22:27   0:00 tcpdump

$ ps axo user,ppid,pid,command | grep apache
root           1   15593 /usr/sbin/apache2 -k start
www-data   15593   15594 /usr/sbin/apache2 -k start
www-data   15593   15595 /usr/sbin/apache2 -k start

This ensure stability of the whole O.S. since the service can break without impacting the rest of processes or files.

"Oh dear! We are in trouble!"

Your user ID/UID have been used to : (pick one)

  • Deface the corporate website
  • Blackmail someone
  • Delete production data and all backups
  • Shut down the main server in the middle of an important task

Your UID is what makes you, you.
So you will be held responsible for its actions, unless we can prove someone else did.
(As shown earlier switching accounts leaves traces, and sudo commands too)

The interesting case of root:
"I solemnly swear that i am up to no good"

Let say 4 people did launch a login shell root on same server, one of them is the bad guy.

  • Abuse of the account occurred at 11AM.
  • /var/log/auth.log shows all 4 sessions starts near 10AM and all finish near noon.
  • As discussed above the history file doesn't contain the command used.
  • Investigation shows that log files haven't been manually tempered with.

In this case, it's nearly impossible to prove (with the O.S. default),
who did what and when, which includes the impossibility to easily prove innocence as well.
Of course, people which did grant root access to all those people might be in trouble too.

-> By chance, you read this article and you are not one of those users.

2021 working as root, still a requirement ?

In modern systems, in most default configurations, if you're an admin you'll be able to launch any command as any user, therefore you can perform any operation anywhere on the filesystem and even add your user in any group.

You wouldn't need to open a shell as root if :

  • Rather than typing 20 command suffixed with sudo you group them in a script.
  • You can sudo
    • vim (If you prefer to use "ed", it's fine.)
    • apt
    • systemctl
  • You are in the needed groups
    • Most of the folders are in 755 so everyone can cd in.
    • If your custom app allows it the folder should belong to a specific group to allow editing without elevation.
    • Non-confidential configuration files in /etc are readable to everyone
    • Log files are readable by the adm group or by everyone
      drwxr-x--- 2 root   adm        4096 Nov 15 16:09 apache2
      drwxr-xr-x 2 root   root       4096 Nov 15 16:09 apt
      -rw-r----- 1 root   adm     1928043 Nov 15 16:18 auth.log
      -rw-rw-r-- 1 root   utmp     292292 Nov 15 16:18 lastlog
      -rw-r--r-- 1 root   root       7299 Nov 15 16:09 dpkg.log		
    • Web files are readable to group www-data

As stated in the previous Debian and Red Hat references, sharing root must be avoided.

In the filesystem the standard groups are used to ease the administration when you're not root. You can have a look to the default groups in the Red Hat Reference, or you should give a glimpse at /etc/groups.

Root elevation is required only if you need to write some file down as most of the content that you may need to read is accessible via group or standard permissions.

Some binaries are setuid, they change UID so you don't have to.

Remember admins are lazy and typing passwords is exhausting (they say),
a well configured OS is the one were you can perform most tasks without elevating once.
Remember that scripts can't be setuid, but compiled applications can.
// use absolute paths or appropriate C fonctions, in doubt see the man
So it's really easy to allow a group to perform elevated tasks in a transparent way.

Good Habits

Since many years I do manage a bunch of servers and since COVID-19, a dozen more VMs for my students.
Like many admins I hate when someone break "my" servers.
Giving root (via password, sudo, or vulnerability) to someone is the quickest way to mess with the whole server.

To avoid that, I leverage the Linux capabilities, and some distributions like Red Hat even enable SELinux in enforce mode by default. Both aims to reduce the power of root.
Those allows to grant or drop (root, but others as well) rights/permissions on a specific ressource, this avoid to give the user the right to break everything.
// Note : Docker use those to ensure isolation between host and container.
Well configured it can be used to automatically grant permissions without any manual elevation from the end user.

It helps to have templates, preconfigured images/packages, scripts and binaries to deploy in minutes what can take hours.
Capabilities, wrappers, chroot and setuid applications are helpful to delegate just the amount of privilege the user need to perform simple tasks when they require them without risking sacrificing the server.

Some readers will remind that Debian originally didn't accept sudo as a solution.
That's true ! Purists think only root shall be root, and they're right to think so.

Every distribution agrees on the fact that you shouldn't share root.

That's not a coincidence if sudo displays :

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

Resources & final thoughts

If you have to work with privileges, you should consider reading the Admin Guide of your distribution : You may learn a lot of tips and tricks to make your life easier.

At the end, often bad habits aren't that hard to fight.
Nothing a bit a knowledge can't fix.
A few modifications on how the system is configured can spare hours of work.
Every operation that take seconds several times per day can be spared.

Use of root / sudo should be limited to "write" operations such as install packages, change configs, start new services so there's very few occasions to perform them.

The root or sudo prompt should always send the following message :
"I'm about to do something dangerous !"
Then it must be reserved for dangerous operations to keep its meaning.

If you have any doubt, don't copy+paste 'stackoverflow' or other internet random sources without reading the product documentation, a 'quick fix' often leads to more constraints in the future.

  1. Stay standard :
    • If the team responsible for a distribution or a standard enable something by default it's because it resolve a previous issue. Things have their reasons to be, and are duly discussed at length among experts and committees.
    • Read the doc and don't break or disable things, eg of bad ideas :
      • set your UID 0
      • chmod -R 777 /
      • Disable SELinux
      • set your private IP with a public range IP
      • ...
  2. Keep It Simple & Stupid.
  3. Invest on fixing the root cause, not the symptoms.

Dive-in ?

Stay-tuned for a hands-on were we'll get a badly configured server and fix it !