Security Basics
OS Security Basics
This lesson covers
The OS as the attacker's ultimate target → User accounts and privilege separation → File permissions and what they actually protect → Processes, services, and attack surface → The kernel and why ring levels matter → Practical OS hardening from the command line
Every attack — no matter how it starts — eventually lands on an operating system. A phishing email delivers a payload that runs as a process. A web application exploit drops a shell. A misconfigured cloud instance gets accessed over SSH. The OS is the final battlefield. Understanding how it manages users, files, processes, and privileges tells you both how attackers move once they're in and exactly where the controls that stop them need to be placed.
User accounts and privilege separation
The most fundamental security mechanism in any OS is the separation between privileged and unprivileged execution. Not every process, user, or application needs — or should have — full control over the system. The damage an attacker can do is directly proportional to the privilege level of the account or process they've compromised.
On Linux, root is the superuser — UID 0, unrestricted access to every file, process, and system call on the machine. A process running as root that gets exploited gives an attacker complete control. This is why well-designed services drop privileges after startup: a web server binds to port 443 as root (because ports below 1024 require it), then immediately switches to an unprivileged user like www-data for all subsequent operations. If the web server gets compromised, the attacker lands as www-data, not root.
On Windows, the equivalent split is between standard users and Administrator accounts, with UAC — User Account Control — acting as a gate that requires explicit approval before a standard process can elevate. The practical security principle is the same: day-to-day work happens as an unprivileged user. Privilege is granted explicitly, temporarily, and only when required.
# See all users on the system and their UIDs
cat /etc/passwd | cut -d: -f1,3,7
# Identify accounts with UID 0 (root-level) — should only be root
awk -F: '($3 == 0) {print}' /etc/passwd
# List members of the sudo group (who can escalate to root)
getent group sudo
# Check which commands a user can run as root via sudo
sudo -l -U username
# Find SUID binaries — programs that run as their owner regardless
# of who executes them (common privilege escalation vector)
find / -perm -4000 -type f 2>/dev/null
What just happened
The first two commands show every account on the system and immediately flag any that have UID 0 — there should be exactly one, root. Any others are a serious red flag. The sudo group check shows who can escalate to root — that list should be short and deliberate. The SUID binary search is one of the first things an attacker runs after getting a foothold, looking for executables that run as a privileged owner regardless of who launches them. If you find unexpected SUID binaries, investigate immediately.
File permissions — the access control built into the OS
Every file and directory on a Linux system has three permission sets: one for the owner, one for the group, and one for everyone else. Each set controls read, write, and execute access independently. Most security misconfigurations at the file level come from permissions being set too broadly — files world-writable when they should be owner-only, or executables accessible to all users when only one service needs them.
# View permissions in human-readable form
ls -la /etc/shadow
# Output:
# -rw-r----- 1 root shadow 1024 Jun 10 09:14 /etc/shadow
# ↑ ↑ ↑
# owner=rw group=r others=none
# Only root can write. Only shadow group can read. Everyone else: nothing.
# Find world-writable files (any user can modify — dangerous)
find /etc -perm -o+w -type f 2>/dev/null
# Find world-writable directories
find / -perm -0002 -type d 2>/dev/null
# Fix an overly permissive file
chmod 640 /etc/myconfig.conf # owner=rw, group=r, others=none
chown root:www-data /etc/myconfig.conf # owned by root, readable by web server group
What just happened
/etc/shadow stores hashed passwords — it's intentionally readable only by root and the shadow group. The world-writable searches are standard hardening checks: any file in /etc that any user can modify is a potential privilege escalation path. The chmod 640 and chown combination at the end shows the correct approach — give the minimum permissions needed, owned by the right user, readable by only the group that needs it.
Processes and services — the running attack surface
Everything running on an OS is a process. Each process runs under a user account, inherits that account's privileges, and can interact with the system only within those privileges. An attacker who exploits a process inherits exactly what that process had — no more. This is why the user a service runs under matters as much as whether the service has vulnerabilities.
Services are long-running processes — web servers, databases, SSH daemons — that start at boot and handle incoming connections. Each one is a potential entry point. A service with a vulnerability, exposed to the network, running as a privileged user, is three problems compounding into one serious risk. Reducing attack surface means running only the services you need, as the least-privileged user possible, with network exposure limited to what's required.
# List all running processes with user context
ps aux
# Show only services managed by systemd and their state
systemctl list-units --type=service --state=running
# Check which user a specific service runs as
systemctl show nginx -p User,Group
# Disable a service that shouldn't be running
systemctl stop cups # Example: print spooler on a server
systemctl disable cups # Prevent it starting on next boot
# List processes listening on network ports with owning user
ss -tlnp | grep LISTEN
What just happened
ps aux shows every process, who owns it, and what it's running — the starting point for spotting unexpected processes after a compromise. systemctl show reveals the user context a service runs under — if nginx is running as root, that's a configuration problem. The cups example is a classic: print spoolers have no business running on a server, yet they're enabled by default on many Linux distributions and have had remotely exploitable vulnerabilities. Disable what you don't use.
The kernel and ring levels
The kernel is the core of the OS — the software that manages hardware, memory, processes, and system calls. It runs in a privileged execution mode called ring 0 — the innermost ring, with unrestricted hardware access. Everything else — applications, services, even most of the OS — runs in ring 3, user space, with no direct hardware access. To do anything that requires hardware interaction (read a file, open a network connection, allocate memory), a user-space process must ask the kernel via a system call.
This separation is fundamental to OS security. A bug in a user-space application is contained — it can only damage what that process can access. A bug in the kernel is catastrophic — it runs in ring 0, with access to everything. Kernel exploits are rare, difficult to write, and extraordinarily powerful. When one is available, it typically grants an attacker complete, undetectable control of the machine regardless of what user-space controls are in place.
Dirty COW — a kernel exploit that took 9 years to find
CVE-2016-5195, known as Dirty COW, was a race condition in the Linux kernel's copy-on-write mechanism that had existed since 2007. Any unprivileged local user could exploit it to write to read-only memory and escalate to root in seconds. It affected virtually every Linux system on the planet. The patch was rushed out within days of disclosure — but the vulnerability had been silently exploitable for nine years before anyone noticed. Kernel vulnerabilities are rare. When they surface, they're treated as emergencies for good reason.
Practical OS hardening — the immediate wins
Most OS-level compromises don't require a kernel exploit. They exploit misconfigured permissions, unnecessary services, weak user account controls, or missing patches. The hardening steps below address the most commonly exploited weaknesses without requiring advanced knowledge — and they apply to any Linux server before it touches a network.
# ── 1. Lock the root account from direct SSH login ──
# Edit /etc/ssh/sshd_config:
# PermitRootLogin no
# PasswordAuthentication no (use SSH keys only)
systemctl restart sshd
# ── 2. Remove packages that don't belong on a server ──
apt purge telnet ftp rsh-client rsh-server xinetd 2>/dev/null
# ── 3. Set password ageing for local accounts ──
# Max 90 days, warn 14 days before expiry
chage -M 90 -W 14 username
# ── 4. Lock inactive accounts automatically ──
useradd -D -f 30 # Lock accounts 30 days after password expires
# ── 5. Restrict cron to authorised users only ──
echo "root" > /etc/cron.allow
rm -f /etc/cron.deny
# ── 6. Set the sticky bit on world-writable directories ──
# Prevents users from deleting each other's files in shared dirs
chmod +t /tmp
chmod +t /var/tmp
# ── 7. Check for unowned files (often left by deleted accounts) ──
find / -nouser -o -nogroup 2>/dev/null
What just happened
Seven independent controls, each closing a specific attack path. Disabling root SSH forces attackers to compromise a regular account first before escalating. Removing legacy protocols (telnet, rsh) eliminates services that transmit credentials in plaintext. The sticky bit on /tmp prevents a classic privilege escalation technique where an attacker plants a file in a shared directory and waits for a privileged process to interact with it. The unowned file search finds artefacts left behind by deleted accounts — sometimes those files are still executable, still have SUID set, and still run as a user that no longer officially exists.
Instructor's Note
The commands in this lesson are not theoretical. Run them on any system you have access to — your home lab, a cloud VM, a local virtual machine — and you will almost certainly find something worth investigating. A world-writable directory you didn't know about. An SUID binary that shouldn't be there. A service running as root that could run as nobody. OS hardening is not a one-time task. It's a regular audit habit, and it starts with knowing how to ask the OS what it's actually doing.
Practice Questions
A file permission bit that causes an executable to run with the privileges of the file's owner rather than the user who launches it — a common privilege escalation vector when found on unexpected binaries. What is this permission bit called?
The kernel runs in a privileged execution mode with unrestricted hardware access. What is this execution level called?
A web server binds to port 443 as root during startup, then immediately drops privileges to run subsequent operations as a low-privileged user. On Debian/Ubuntu systems, what is the conventional unprivileged user that web servers like Apache and Nginx run as?
Quiz
Kernel vulnerabilities are treated as critical emergencies even when they require local access to exploit. What makes a kernel exploit categorically more dangerous than a user-space exploit?
A Linux server runs nginx as the www-data user rather than root. The nginx process has a vulnerability that allows remote code execution. Why does this configuration limit the damage?
The sticky bit is set on /tmp by default on most Linux systems. What specific attack does this prevent?
Up Next · Lesson 12
Linux Security Fundamentals
From mandatory access controls to audit frameworks — Linux gives you more security levers than almost any other OS. This lesson shows you how to pull them.