Local Security
Account Security Foundations
Section titled “Account Security Foundations”The Linux security model is built on the principle of least privilege: every user, process, and daemon should have only the minimum permissions required to do its job - nothing more.
Account Types and Privilege
Section titled “Account Types and Privilege”| Account Type | UID | Privileges | Typical Use |
|---|---|---|---|
root | 0 | Unlimited - no DAC restrictions | System administration only |
| System accounts | 1-99 | Very limited; no login | Core OS services (sshd, mail) |
| Service accounts | 100-999 | Limited to specific directories | Application services (nginx, postgres) |
| Normal users | 1000+ | Access to own files and permitted devices | Human users |
The last utility shows login history - useful for spotting dormant accounts:
last # full login historylast -n 10 # last 10 loginslastb # failed login attempts (root only)Operations Requiring Root Privileges
Section titled “Operations Requiring Root Privileges”| Requires root | Does NOT require root |
|---|---|
| Create/remove user accounts | Run network clients (browsers, SSH clients) |
| Install/remove system packages | Print using permitted printers |
Modify files in /etc, /lib, /boot | Access files with proper permissions |
| Restart system services | Run SUID programs (e.g., passwd) |
| Load kernel modules | Use devices accessible to your group |
The goal: root should be invoked only when strictly necessary, and every root action should be auditable.
sudo vs su
Section titled “sudo vs su”| Feature | su | sudo |
|---|---|---|
| Authentication | Root’s password | Your own password |
| Persistence | Full root shell until exit (unlimited time) | Per-command; re-prompts after timeout (5-15 min) |
| Granularity | All-or-nothing | Per-command, per-user, per-host control |
| Logging | Minimal | Every command logged with user identity |
| Risk | Root password must be shared | Root password stays secret |
| Audit trail | Poor | /var/log/auth.log or /var/log/secure |
Best practice: Disable direct root login. Use sudo for all elevated operations.
su - # login shell as root (bad practice)sudo command # run ONE command as root (preferred)sudo -i # root login shell via sudo (audited)sudo -u alice command # run as a different usersudo -l # list what you're allowed to doThe sudoers Configuration
Section titled “The sudoers Configuration”Configuration Files
Section titled “Configuration Files”| Location | Purpose |
|---|---|
/etc/sudoers | Master configuration file |
/etc/sudoers.d/ | Drop-in directory; one file per user or group (preferred) |
Entry Format
Section titled “Entry Format”who where = (as_whom) what# Examples in /etc/sudoersowl ALL=(ALL) ALL # full unrestricted sudoalice ALL=(root) /usr/bin/apt # only apt, only as rootbob ALL=(ALL) NOPASSWD: /usr/bin/rsync # rsync without password prompt%devs ALL=(ALL) ALL # group devs gets full sudocarol ALL=(www-data) /usr/sbin/apachectl # switch to www-data only
# Restrict to specific hostsdave webserver=(root) /usr/bin/systemctl restart nginxKey syntax:
ALLin thewherefield = any hostALLin(as_whom)= any user (including root)ALLinwhat= any command%groupname= apply rule to a groupNOPASSWD:= skip password prompt for that command
Logging sudo
Section titled “Logging sudo”By default, all sudo executions and failures are logged:
| Distribution family | Log location |
|---|---|
| Debian/Ubuntu | /var/log/auth.log |
| RHEL/Fedora/CentOS | /var/log/secure or /var/log/messages |
Each log entry includes: calling user, terminal, working directory, target user, command + arguments.
A failed sudo attempt looks like:
bjmoose : user NOT in sudoers ; TTY=pts/4 ; PWD=/var/log ; USER=root ; COMMAND=/usr/bin/tail securePassword Security
Section titled “Password Security”Storage Mechanisms
Section titled “Storage Mechanisms”Historical problem: /etc/passwd is world-readable (needed by system programs). Early UNIX stored password hashes there - attackers could copy the file and run offline cracking tools.
Solution: /etc/shadow with permissions 000 to 400 (root-read-only). Passwords are stored here as one-way hashes.
SHA-512 Hashing
Section titled “SHA-512 Hashing”Modern Linux uses SHA-512 for password hashing. The stored format in /etc/shadow:
$6$<salt>$<hash>$6$= SHA-512 algorithm identifier<salt>= 8-character random value (prevents rainbow table attacks)<hash>= 88-character SHA-512 hash ofsalt + password
The salt means two users with the same password have completely different hash values. Even if an attacker gets the shadow file, they must brute-force each account separately.
PAM - Pluggable Authentication Modules
Section titled “PAM - Pluggable Authentication Modules”PAM is the authentication abstraction layer in Linux. Applications (login, sshd, su, sudo) delegate all authentication decisions to PAM rather than implementing their own.
PAM policy is configured in /etc/pam.d/:
ls /etc/pam.d/ # per-application PAM configscat /etc/pam.d/passwd # policy for the passwd commandPAM enforces password quality through modules:
pam_cracklib.so(older) /pam_pwquality.so(newer): Enforces minimum length, complexity requirements, dictionary checkspam_faillock.so: Locks accounts after N failed attempts (brute-force protection)pam_unix.so: Standard Unix password verificationpam_securetty.so: Restricts root login to terminals listed in/etc/securettypam_limits.so: Enforces resource limits from/etc/security/limits.conf
Good Password Practices
Section titled “Good Password Practices”| Practice | Mechanism |
|---|---|
| Password aging | chage (force rotation after N days) |
| Complexity requirements | PAM (pam_pwquality.so) |
| Account lockout on failures | PAM (pam_faillock.so) or faillock |
| Multi-factor authentication | PAM (pam_google_authenticator.so, etc.) |
| Audit credential usage | sudo logging + auditd |
# Check who has empty passwords (security audit)sudo awk -F: '$2=="" {print $1}' /etc/shadow
# Check for accounts with no expiry policysudo chage -l username
# Force immediate password change at next loginsudo chage -d 0 usernameProcess Isolation
Section titled “Process Isolation”Linux security starts with fundamental kernel-level isolation:
- Separate address spaces: Each process has its own virtual memory - a process can’t read another’s memory without explicit mechanisms (shared memory, pipes)
- Separate credentials: Each process runs with a UID/GID; kernel enforces DAC on every syscall
- No implicit trust: Processes can’t access each other’s files, sockets, or descriptors without kernel-mediated sharing
Additional isolation mechanisms that extend the baseline:
| Mechanism | What it isolates | Notes |
|---|---|---|
| cgroups | CPU, memory, I/O, processes | Limits resource use per group of processes |
| Namespaces | PID, network, mount, user, UTS, IPC | Foundation of containers |
| Containers | Full OS tree per service | Uses namespaces + cgroups; no hypervisor |
| Virtualization | Entire hardware environment | Full isolation; performance overhead |
| seccomp | System calls | Restricts which syscalls a process can invoke |
| capabilities | Fine-grained root privileges | Split root’s power into ~40 separate capabilities |
Hardware Device Access
Section titled “Hardware Device Access”Linux enforces device security through the /dev filesystem - devices are special files with owner:group:permissions just like regular files:
ls -l /dev/sda# brw-rw---- 1 root disk 8, 0 ... /dev/sda# disk group - users in 'disk' group can accessls -l /dev/tty# crw-rw-rw- 1 root tty 5, 0 ... /dev/ttyTo give a user direct access to a device, add them to the appropriate group:
sudo usermod -aG disk alice # disk accesssudo usermod -aG audio alice # audio devicessudo usermod -aG video alice # video devicesSecuring the Boot Process
Section titled “Securing the Boot Process”GRUB Bootloader Security
Section titled “GRUB Bootloader Security”GRUB 2 can require a password to:
- Modify boot parameters (prevent passing
init=/bin/shto get a root shell) - Boot specific menu entries
# Generate a hashed GRUB passwordgrub2-mkpasswd-pbkdf2# Enter your password at the prompt# Outputs: grub.pbkdf2.sha512.10000.LONG_HASH_STRING
# Add to GRUB configuration in /etc/grub.d/40_custom:# set superusers="admin"# password_pbkdf2 admin grub.pbkdf2.sha512.10000.LONG_HASH_STRING
# Regenerate grub configsudo grub2-mkconfig -o /boot/grub2/grub.cfg # RHEL/Fedorasudo update-grub # Debian/UbuntuPhysical Security Threats
Section titled “Physical Security Threats”When hardware is physically accessible:
| Threat | Prevention |
|---|---|
| Keyboard sniffing | Physically secure keyboard access; use full-disk encryption |
| Boot from live USB/DVD | BIOS password + boot order lock |
| Cold boot attack (RAM) | Full-disk encryption with memory locking |
| Remove disk and mount elsewhere | Full-disk encryption (LUKS) |
| Network packet sniffing | TLS everywhere; encrypted VPNs; network segmentation |
Guidelines:
- Lock workstations and servers physically
- Encrypt sensitive disks with LUKS (Linux Unified Key Setup)
- Disable unused network interfaces and ports
- Keep BIOS/UEFI firmware updated