Users#

Identity is where every operation begins. The operator lands on a box as some UID with some primary GID and a supplementary group list, and that triple decides what the next syscall is allowed to do. Reading the identity layer fast (id, whoami, getent, groups) is the first move on an unfamiliar host, friendly or hostile.

The model is POSIX-defined (<sys/types.h> defines uid_t and gid_t), so the same enumeration tradecraft holds on Linux, BSD, and macOS. Every file-access check, every setuid transition, every kernel permission gate runs against this triple, and so does every privilege-escalation finding the operator writes up.

┌────────────────────────── Process Identity ──────────────────────────┐
│                                                                      │
│   UID  ──────────►  who am I            (owner of the process)       │
│                                                                      │
│   GID  ──────────►  primary group        (default group on new files)│
│                                                                      │
│   Groups  ──────►   supplementary list   (member of: sudo, docker,   │
│                                          users, wheel, video, ...)   │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘
                       │
                       │ kernel checks against
                       ▼
┌────────────────────────────────────────────────────────────────────────┐
│   File:  -rw-r-----  operator  staff   secrets.txt                     │
│            │   │   │    │       │                                      │
│            │   │   │    │       └─  group  →  must be in supplementary │
│            │   │   │    └─────────  owner  →  must match UID           │
│            │   │   └──────────────  others →  fallback                 │
│            │   └──────────────────  group bits                         │
│            └──────────────────────  owner bits                         │
└────────────────────────────────────────────────────────────────────────┘

Home#

Each user has a home directory ($HOME, configured in /etc/passwd, abbreviated as ~). The convention is /home/USER for regular users and /root for root. Personal config lives there as dotfiles (filenames starting with ., hidden from ls by default). Newer applications follow the XDG Base Directory layout, which separates config, cache, data, and state into their own paths.

Path

Environment variable

Purpose

~/.bashrc

(none)

Classic dotfiles for shell, SSH, GnuPG (per-app conventions)

~/.config/

$XDG_CONFIG_HOME

User config (preferences, profiles)

~/.cache/

$XDG_CACHE_HOME

Disposable cached data; safe to delete

~/.local/share/

$XDG_DATA_HOME

Persistent app data (databases, history)

~/.local/state/

$XDG_STATE_HOME

Runtime state (logs, undo files, lockfiles)

~/.local/bin/

(none)

Per-user executables on $PATH

whoami prints just your username:

$ whoami
operator

$HOME is the absolute path to your home directory:

$ echo $HOME
/home/operator

id prints the full identity (UID, primary GID, supplementary groups):

$ id
uid=1000(operator) gid=1000(operator) groups=1000(operator),27(sudo),100(users)

List the dotfiles in $HOME:

$ ls -la ~
drwx------ 5 operator operator 4096 May  1 09:14 .
drwxr-xr-x 3 root     root     4096 Apr 28 17:02 ..
-rw------- 1 operator operator  220 Apr 28 17:02 .bashrc
drwx------ 2 operator operator 4096 Apr 28 17:05 .ssh

Shells#

A user’s login shell is the program init execs after authentication, recorded as the last field of the entry in /etc/passwd. Available shells are listed in /etc/shells, and chsh rewrites the entry for the current user.

$SHELL holds the path of your login shell:

$ echo $SHELL
/bin/bash

List every shell installed on the system:

$ cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/zsh
/usr/bin/fish

A line in /etc/passwd is seven colon-separated fields. Knowing each field on sight saves time when reading getent passwd output or auditing a foreign system.

$ cat /etc/passwd
operator:x:1000:1000:Operator:/home/operator:/bin/bash

/etc/passwd line format:

operator : x : 1000 : 1000 : Operator,,, : /home/operator : /bin/bash
    │     │     │      │          │              │              │
    │     │     │      │          │              │              └─ login shell
    │     │     │      │          │              └─ home directory
    │     │     │      │          └─ GECOS comment (full name etc.)
    │     │     │      └─ primary GID
    │     │     └─ UID  (0 = root, <1000 = system, ≥1000 = real)
    │     └─ password placeholder ('x' = look in /etc/shadow)
    └─ login name

getent queries the system databases (passwd, group, hosts); useful when entries come from LDAP or SSSD, not just /etc/passwd:

$ getent passwd $USER
operator:x:1000:1000:Operator:/home/operator:/bin/bash

chsh -s rewrites the login-shell field of /etc/passwd:

$ chsh -s /usr/bin/zsh
Password:
(no further output; takes effect at next login)

Groups#

A user belongs to one primary group and zero or more supplementary groups. Group membership controls file access and which privileged devices or services you can use without sudo: members of docker get the Docker socket, members of wireshark can capture packets, and so on.

groups lists the group names you belong to:

$ groups
operator sudo users

id -Gn prints the same list using id; useful in scripts:

$ id -Gn
operator sudo users

Look up who is in a given group:

$ getent group sudo
sudo:x:27:operator,alice

usermod -aG adds a user to a supplementary group; the change takes effect on the next login (or via newgrp):

$ sudo usermod -aG docker operator
(no output; check with ``id`` after re-login)

Switch#

su switches to another user. su - (with the dash) starts a fresh login shell that re-reads the new user’s profile, environment, and $PATH; plain su USER keeps the current shell’s environment, which is usually not what you want for an admin task.

Become root with a full login shell:

$ su -
Password:
root@system:~#

Become another regular user with their environment:

$ su - operator
Password:
operator@system:~$

Switch to a service account while keeping your current shell environment:

$ su postgres
postgres@system:/home/operator$

Sudo#

sudo is the controlled way to run a single command as root (or another user) while keeping an audit trail of who ran what and when. Privileges are governed by /etc/sudoers and drop-ins under /etc/sudoers.d/, edited only with visudo.

The decision tree below is what the operator should run through when they need elevated privilege. su and sudo answer different questions; picking the wrong one produces audit gaps, lost env vars, or denied access.

        flowchart LR
    Q(["Need to run a command<br/>as another user"])
    Q -->|"as root, audited"| A1["sudo CMD"]
    Q -->|"as root, interactive shell"| A2["sudo -i (clean env)<br/>sudo -s (current env)"]
    Q -->|"as some other user, one cmd"| A3["sudo -u USER CMD"]
    Q -->|"what am I allowed to do"| A4["sudo -l"]
    Q -->|"edit sudoers safely"| A5["sudo visudo<br/>sudo visudo -c (validate)"]
    Q -->|"service account, have password"| A6["su - USER"]
    Q -->|"full root login shell, no sudo"| A7["su -"]
    

Form

Effect

sudo CMD

Run command as root

sudo -i

Open an interactive root shell

sudo -u USER CMD

Run command as another user

sudo -l

List what you’re allowed to run

sudo visudo

Safely edit /etc/sudoers

Run a single command as root; only root can read /etc/shadow:

$ sudo cat /etc/shadow
[sudo] password for operator:
root:$6$...:19234:0:99999:7:::
...

Open an interactive root shell:

$ sudo -i
root@system:~#

Run a command as a non-root user (e.g. open a Postgres shell as the postgres user):

$ sudo -u postgres psql
psql (16.1)
Type "help" for help.
postgres=#

List what your account is allowed to run with sudo:

$ sudo -l
User operator may run the following commands on system:
    (ALL : ALL) ALL

Common Tasks#

Enumerate accounts (real users, system users, service accounts).

$ getent passwd
$ awk -F: '$3>=1000 && $1!="nobody"{print $1}' /etc/passwd
$ awk -F: '$7~/(bash|zsh|sh|fish)$/{print $1,$7}' /etc/passwd

Audit privileged access (who is in the wheel/sudo/admin set, who has root).

$ getent group sudo wheel admin
$ sudo cat /etc/sudoers
$ sudo ls -la /etc/sudoers.d/
$ sudo grep -rE 'NOPASSWD|ALL=' /etc/sudoers /etc/sudoers.d/ 2>/dev/null

Login history (who has touched the box).

$ last -F | head -30
$ lastlog | awk '$2!="**Never"'
$ sudo journalctl _COMM=sshd | tail -50
$ who; w

Password / lock state (which accounts can authenticate).

$ sudo passwd -S -a
$ sudo awk -F: '$2!~/^[!*]/{print $1}' /etc/shadow
$ sudo chage -l <user>

Hunt persistence (new accounts, weird shells, suspect home dirs).

$ sort /etc/passwd | awk -F: '{print $1,$3,$7}' | sort -k2 -n
$ find /home /root -maxdepth 3 -name '.ssh' -exec ls -la {} \;
$ awk -F: '$3==0{print $1}' /etc/passwd

Add / disable a user safely (for cleanup or for an authorized test account).

$ sudo useradd -m -s /bin/bash -G sudo opuser
$ sudo passwd opuser
$ sudo usermod -L baduser
$ sudo userdel -r baduser

Switch identities (run as another user, drop into root).

$ sudo -i                    # full root login shell
$ sudo -u www-data -s        # shell as a service user
$ su - <user>
$ id; whoami; groups

Manage groups (add, remove, change membership).

$ getent group <group>
$ sudo groupadd ops
$ sudo usermod -aG sudo,ops <user>     # -aG, never plain -G
$ sudo gpasswd -d <user> <group>

Set or expire a password (including force-change on next login).

$ sudo passwd <user>
$ sudo passwd -e <user>                # expire now
$ sudo chage -M 90 -m 7 -W 14 <user>   # aging policy

See active sessions (who is logged in right now).

$ who; w; users
$ loginctl list-sessions
$ ps -eo user,tty,pid,cmd | grep -v '^root'

Edit sudoers safely (syntax-checked).

$ sudo visudo
$ sudo visudo -f /etc/sudoers.d/ops
$ sudo visudo -c                       # validate without editing

References#

  • man 5 passwd, man 5 shadow, man 5 group (account database file formats).

  • man 5 sudoers, man 8 sudo, man 8 visudo (sudo policy and editor).

  • man 1 id, man 1 whoami, man 1 groups, man 1 getent (identity lookup).

  • man 1 su, man 1 chsh, man 8 useradd, man 8 usermod, man 8 userdel, man 1 passwd, man 1 chage (account management).

  • Permissions for the permission, sudoers, and capability layer that consumes this identity.

  • Shells for per-shell coverage and login behavior.

  • Linux for the command quick-reference.

  • XDG Base Directory Specification