How to read this primer
This is a read-through, not a hands-on lab — every command shows representative output so you can learn it without running anything. It is the conceptual foundation the FIDO and Secure Boot labs build on: identity, permissions, PAM, services, and exposure. A few conventions carry throughout.
The label above each block tells you the privilege
Every command block is tagged. Normal user shell runs as an ordinary user. Uses sudo needs administrator rights — you will be asked for your own password, and the command runs as root for that one invocation.
Command blocks vs. OUTPUT blocks
Blocks with a copy button are commands you could type. Dimmed blocks headed OUTPUT show representative results — nothing to run. A red DESTRUCTIVE header flags a command that is irreversible; read the path twice before you would ever run it.
Security lens
Amber Security lens callouts call out the stakes: how a setting gets abused, and what to check. Red callouts mark something that can destroy data or lock you out.
mint, an admin
labadmin, plain users user1–user4, a stand-in intruder
rogue1, and the lab network 192.168.56.x. All are illustrative placeholders.
Commands are shown for Linux Mint and behave the same across Debian- and Ubuntu-based systems.
1. Linux & the shell
Linux is a family of open-source operating systems built on a shared kernel — the core that manages the CPU, memory, devices, and processes. Everything you type goes through a shell, the program that turns your commands into requests the kernel carries out. Mint is one Linux distribution among hundreds; it is based on Ubuntu, which is based on Debian, which is why its commands match most of the Linux world.
Reading the shell prompt
The prompt tells you who and where you are. The final character is the tell that matters most:
$ means an ordinary user, # means root — the all-powerful superuser.
whoami
Example output
labadmin
Example prompts
labadmin@mint:~$ the trailing $ -> an ordinary user
root@mint:~# the trailing # -> you are root, no guardrails
#
means a single typo can rewrite or destroy system files with no "are you sure?" — root has no
guardrails. This primer uses sudo for one-off admin commands so you spend as little
time as possible sitting at a # prompt.
2. Navigating the filesystem
Linux has no drive letters. Everything hangs off a single root, written / — think of the
filesystem as a tree whose trunk is /, whose branches are directories, and whose leaves
are files. Paths are either absolute (start at /) or relative (start
where you are). Names are case-sensitive: Notes.txt and notes.txt are two
different files.
The key directories
A handful of top-level directories carry most of the security weight:
| Path | What lives there |
|---|---|
/home | Per-user home directories (/home/labadmin). Each user can read only their own. |
/etc | System configuration — the passwd, group, shadow, PAM, and sysctl files you will harden. |
/boot | Bootloader and kernel. Do not touch unless you mean to. |
/var | Variable data: logs (/var/log), databases, mail. |
/proc | A virtual view into the kernel and every running process — not real files on disk. |
/bin /sbin /usr | Programs. /sbin holds tools meant for root. |
pwd · cd · ls
pwd prints your present working directory. cd changes it. ls
lists what is there. With no argument, cd takes you home and ls lists the
current directory.
pwd
Example output
/home/labadmin
Normal user shell
cd /home/labadmin/Music
cd ../Documents # .. is the parent directory
cd ~ # ~ is a shortcut to your home
.is always the current directory,..the parent,~your home.- Absolute:
cd /etc. Relative:cd Documents(from where you stand).
ls -l -a -la
The options make ls a security tool. -l is the long listing (owner, group,
permissions, size, date). -a shows all files, including hidden ones whose names
start with a dot. They combine as -la.
ls -la
Example output
drwxr-xr-x 14 labadmin labadmin 4096 Jun 12 09:14 .
drwxr-xr-x 4 root root 4096 May 30 11:02 ..
-rw------- 1 labadmin labadmin 220 May 30 11:02 .bash_history
-rw-r--r-- 1 labadmin labadmin 3771 May 30 11:02 .bashrc
drwxr-xr-x 2 labadmin labadmin 4096 Jun 12 09:14 Documents
ls will
not show them — ls -la will. Reviewing hidden files in home directories is a routine hunt
for persistence.
3. Working with files
The everyday verbs: read, create, copy, move, delete, and edit. Two ideas make them powerful — every program has a standard output you can redirect into a file, and the manual is one command away.
man · --help
Never guess. man ls opens the manual for ls; press q
to quit, arrows or PgUp/PgDn to scroll. Most commands
also accept --help for a quick summary. Files have manuals too — man 5 passwd
documents the format of /etc/passwd.
man 5 shadow # section 5 = file formats
ls --help
cat · echo · file
cat prints a file's contents. echo prints whatever you give it.
file tells you what a file actually is, regardless of its name.
cat /etc/hostname
Example output
mint
Normal user shell
file report.pdf
Example output
report.pdf: PDF document, version 1.7
touch · mkdir · cp · mv · rm
touch makes an empty file (or updates a timestamp). mkdir makes a directory.
cp copies, mv moves or renames, rm removes.
touch notes.txt
cp notes.txt notes.bak # copy
mv notes.bak archive/ # move into a directory
rm notes.txt # delete — no recycle bin
rm is immediate and permanent — there is no undo and no
trash on the command line. Run as an administrator, sudo rm -rf on the wrong path can
erase the system. Read the path twice.
rm -rf, demonstrated safely
Worth seeing once — on a throwaway tree under /tmp, so nothing real is at risk. Build a
small directory tree, make every file and folder in it read-only, then watch sudo rm -rf
erase the whole thing anyway, without a single prompt. Everything here is safe to run yourself.
mkdir -p /tmp/rm-demo/keep/nested
touch /tmp/rm-demo/keep/nested/report.txt /tmp/rm-demo/keep/notes.log
chmod -R a-w /tmp/rm-demo # strip write permission from the whole tree
ls -lR /tmp/rm-demo
Example output
/tmp/rm-demo:
total 0
dr-xr-xr-x 3 labadmin labadmin 80 Jul 16 21:00 keep
/tmp/rm-demo/keep:
total 0
dr-xr-xr-x 2 labadmin labadmin 60 Jul 16 21:00 nested
-r--r--r-- 1 labadmin labadmin 0 Jul 16 21:00 notes.log
/tmp/rm-demo/keep/nested:
total 0
-r--r--r-- 1 labadmin labadmin 0 Jul 16 21:00 report.txt
Uses sudo
sudo rm -rf /tmp/rm-demo # gone — read-only did not save it
sudo rm -rf
deleted the entire tree silently — no confirmation, no recovery. Read-only permissions guard against
accidental edits, not against root: the superuser bypasses the permission check entirely. That
is exactly why the red DESTRUCTIVE banner rides on the block above — -f
("force") suppresses every safety prompt and -r makes it recursive. Aim that at the wrong
path as root and there is nothing to bring it back.
redirection > >> < |
Every program reads standard input and writes standard output. Redirect them:
> sends output to a file (overwriting it), >> appends,
< feeds a file in as input, and the pipe | hands one command's output to
the next as input.
echo "hello" > hello.txt # overwrites hello.txt
echo "again" >> hello.txt # appends
cat hello.txt # show what's in the file now
Example output
hello
again
Normal user shell
cat /etc/passwd | wc -l # count user records
Example output
42
> silently destroys whatever the file held. Reach for
>> when appending to logs or config, and double-check before redirecting over a
system file.
head · tail · wc
head shows the first 10 lines, tail the last 10; -n N changes
the count. tail -f follows a file live as it grows — the classic way to watch a log.
wc -l counts lines.
sudo head -n 1 /etc/shadow
Example output
root:!:19700:0:99999:7:::
Uses sudo
sudo tail -f /var/log/auth.log # live view; Ctrl+C to stop
tail -f /var/log/auth.log shows authentication attempts
as they happen — failed logins appear in real time, which makes it a quick tripwire during an incident.
diff · gedit
diff a b reports the lines that differ between two files (< is in the
first, > in the second). gedit opens a file in a graphical editor — the
gentlest way to edit config.
diff sshd_config sshd_config.bak
Example output
32c32
< PermitRootLogin no
---
> PermitRootLogin yes
diff against a known-good backup is how you spot exactly
what an attacker (or a bad change) altered in a config file.
4. Searching & text streams
Finding things fast is half of defense. find walks the filesystem by any property;
locate answers from a prebuilt index; grep searches inside files.
Pipe them together and you have a forensic toolkit.
find
find searches a directory tree and tests each file against expressions — by name, type,
owner, and more — then optionally acts on matches. Searching all of / reads directories
other users own, so it is run with sudo.
sudo find /home -name "*.pdf" # by name
sudo find / -type f -user rogue1 # every file owned by an intruder
Example output
/var/tmp/.cache
/home/rogue1/notes
find / -user rogue1
locates everything it left behind. The same command can find world-writable files or misplaced SUID
binaries — common footholds.
locate · updatedb
locate is far faster than find because it reads a database instead of walking
the disk — but the database can be stale, so refresh it with updatedb first.
sudo updatedb
locate "*.pdf"
grep -R
grep pattern file prints lines matching a pattern; -R searches recursively
through a directory.
sudo grep FAILED /var/log/auth.log # find failed authentications
grep -R "PermitRootLogin" /etc/ssh
FAILED surfaces brute-force
attempts; grepping /etc for a setting tells you where it is configured before you change it.
5. Users, groups & identity
Three files define who exists on the system. /etc/passwd lists accounts,
/etc/group lists groups, and /etc/shadow holds the encrypted passwords. The
operating system identifies everyone by number — a UID and GID — not by name.
/etc/passwd
One line per account, seven colon-separated fields. Despite the name, it no longer holds passwords —
the x means "look in the shadow file."
cat /etc/passwd
Example output
root:x:0:0:root:/root:/bin/bash
labadmin:x:1000:1000:Lab Admin:/home/labadmin:/bin/bash
user1:x:1001:1001:User One:/home/user1:/bin/bash
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
| Field | Meaning |
|---|---|
name | Login name humans use. |
x | Password placeholder — the real hash is in /etc/shadow. |
UID | Numeric user ID. 0 is root. The kernel identifies users by this, not the name. |
GID | Primary group ID. |
comment | Usually the person's real name. |
home | Home directory. |
shell | Program run at login. /usr/sbin/nologin means the account cannot log in interactively. |
The UID is worth reading closely, because its range tells you what kind of account it is:
0— root, the superuser. Onlyrootshould ever have it.1–999— system accounts for services (www-data,sshd, …); these are hidden from the graphical login screen.65534— nobody, the deliberately unprivileged account.1000and up — human users; the first real person is usually1000.
root
with UID 0 — that is an instant backdoor. Second, any login-capable account hiding in the
system range below 1000: a service account should never have a real shell. Then compare the
human accounts (1000+) against who is actually supposed to be on the box — an extra name in
that range is the classic planted account.
/etc/group
Defines groups and their members: name:password:GID:members. Group membership is how
privileges like sudo are granted.
cat /etc/group
Example output
sudo:x:27:labadmin
team1:x:1002:user1,user2
projectx:x:1003:user3
sudo group is the crown jewel — anyone in it can
become root. Review its membership first; an unexpected name here is a privilege-escalation finding.
/etc/shadow
Readable only by root. Holds the hashed password and its aging rules:
name:hash:lastchange:min:max:warn:::. A hash starting $y$ is yescrypt; a lone
! or * means the account has no usable password (locked).
sudo getent shadow labadmin
sudo head -n 1 /etc/shadow
Example output
labadmin:$y$j9T$…hash omitted…:19700:0:90:7:::
root:!:19700:0:99999:7::: # root is locked (! = no password)
passwd file. On Mint, root having no password is intentional: it cannot be logged into
directly.
whoami · id · who · w · getent
whoami is your effective name; id shows your UID, GID, and groups;
who and w list who is logged in (and what they are running); getent
pulls specific records from passwd/group/shadow.
id
Example output
uid=1000(labadmin) gid=1000(labadmin) groups=1000(labadmin),27(sudo)
Normal user shell
getent group sudo
Example output
sudo:x:27:labadmin
su · sudo · sudo -i — changing privilege
There are two ways to act as another user, and here the difference is the whole point, so we sit in a
real root shell to see it. su user becomes that user — you need their
password. sudo command runs a single command as root and asks for your own
password (if you are allowed). sudo -i opens an interactive root shell; sudo su
and su - reach a root shell too, but sudo -i is the clean, logged way.
sudo -i
Example session
[sudo] password for labadmin:
root@mint:~# you are now root — the prompt ends in #
whoami
root
exit leave the root shell as soon as you are done
su to root
fails — that is a feature. sudo is the sanctioned path: it is logged, time-limited, and
needs only your own credentials. Prefer sudo command for one-off tasks, reach for
sudo -i only when you have several to do, and stay root no longer than necessary.
/etc/sudoers · visudo — who may run what
Membership in the sudo group is the usual grant, but the actual rules live in
/etc/sudoers and the drop-in directory /etc/sudoers.d/. Never open sudoers in
a plain editor — visudo checks the syntax before it saves, so a typo cannot lock everyone
out of sudo. sudo -l shows what the current user is permitted to run.
sudo visudo # edit safely — syntax-checked on save
sudo visudo -c # just validate the current file
sudo -l # list what you are allowed to run
Example — /etc/sudoers
root ALL=(ALL:ALL) ALL
%sudo ALL=(ALL:ALL) ALL # everyone in the sudo group
labadmin ALL=(ALL) NOPASSWD: ALL # DANGER: full root with no password prompt
NOPASSWD: ALL means whoever reaches that account is
instantly root with no prompt — a favorite backdoor. Treat any of these as a privilege-escalation
finding: a user or %group line you did not add, a stray file in
/etc/sudoers.d/, or NOPASSWD on a broad command. Audit both
/etc/sudoers and /etc/sudoers.d/ by hand, and confirm a specific user's rights
with sudo -l -U user1.
6. Managing accounts & permissions
Creating and removing users and groups, setting passwords, and controlling exactly who can read, write, or run each file. Permissions are the everyday access control of Unix.
adduser · deluser (useradd · userdel)
On Mint, prefer the friendly adduser/deluser — they create the home directory
and prompt for a password. useradd/userdel are the lower-level tools that
exist on every distribution.
sudo adduser user4 # create, with home + prompts
sudo deluser --remove-home rogue1 # remove an intruder and their files
--remove-home
(or a later find -user sweep) makes sure nothing they planted is left behind.
addgroup · delgroup · gpasswd
addgroup/delgroup create and delete groups. gpasswd -a user group
adds a member; -d removes one.
sudo addgroup projectx
sudo gpasswd -a user3 projectx # add user3 to projectx
sudo gpasswd -d user2 sudo # revoke someone's admin rights
passwd
passwd changes a password — your own by default, or another user's if you are root.
passwd -l locks an account, -e forces a change at next login.
sudo passwd user1 # set a strong password for user1
sudo passwd -l user2 # lock a suspicious account
Reading permissions
Every file has an owner, a group, and three permission sets — for the user (owner), the
group, and others. Each set grants read (r), write (w), or
execute (x). The ten-character string at the front of ls -l encodes it all.
ls -l script.sh
Example output
-rwxr-x--- 1 labadmin team1 2048 Jun 12 09:14 script.sh
| Piece | Reads as |
|---|---|
- | Type: - file, d directory, l symlink. |
rwx | Owner labadmin: read, write, execute. |
r-x | Group team1: read and execute, no write. |
--- | Others: nothing. |
chown · chgrp · chmod
chown changes the owner, chgrp the group, chmod the permissions.
Changing ownership needs root; changing the mode on a file you own does not. The symbolic form of
chmod reads left to right: who (u/g/o/a),
how (+ add, - remove, = set), what
(r/w/x).
sudo chown labadmin script.sh # give ownership to labadmin
chmod o-rwx script.sh # others: remove all access
chmod g+x script.sh # group: allow execute
-rw-rw-rw-) lets any user tamper
with it — a classic vulnerability. Strip o (other) permissions from anything sensitive,
and never leave scripts or config writable by "others."
0640 — root
may write it, one login group may read it, everyone else gets nothing. That exact mode exists for the
tampering rule above.
SUID, SGID & the sticky bit
Three special bits sit on top of rwx. SUID (set-user-ID) makes a program
run as its owner rather than as you — it is how passwd, owned by root, can edit
/etc/shadow. SGID does the same for the group. The
sticky bit on a shared directory like /tmp lets anyone create files but
lets each person delete only their own. In ls -l they appear as an s or
t where an x would be.
ls -l /usr/bin/passwd
ls -ld /tmp
Example output
-rwsr-xr-x 1 root root 59976 Mar 23 /usr/bin/passwd # the s = SUID: runs as root
drwxrwxrwt 2 root root 4096 Jul 16 /tmp # the t = sticky bit
Uses sudo
sudo find / -perm -4000 -type f 2>/dev/null # every SUID binary on the system
sudo find / -perm -2000 -type f 2>/dev/null # every SGID binary
Example output
/usr/bin/sudo
/usr/bin/passwd
/usr/bin/mount
/usr/bin/su
sudo chmod u-s /path/to/file.
Capabilities — SUID's finer-grained successor
SUID is all-or-nothing: a SUID-root program gets every root power, even if it needs only one.
Modern Linux splits root's authority into about forty capabilities — discrete powers
like cap_net_bind_service (bind a port below 1024), cap_net_raw (craft raw
packets), or cap_dac_override (ignore file permissions). A binary can be granted just the
one it needs instead of full root. It is why ping on Debian is no longer SUID-root — it
carries cap_net_raw and nothing else.
getcap -r / 2>/dev/null # every file that carries a capability
Example output
/usr/bin/ping cap_net_raw=ep
cap_setuid or cap_dac_override on an
unexpected binary hands out root just as surely as a SUID shell. Run getcap -r / alongside
your SUID sweep, and treat anything you did not expect — especially a capability on a shell or on a file
in a home directory — as a finding.
7. Software & updates
Mint installs software as packages managed by apt (the Advanced Package Tool).
Keeping packages patched is the single highest-value habit in defense — most breaches exploit a known,
already-fixed flaw.
apt update · upgrade · full-upgrade
apt update refreshes the list of available packages (it installs nothing). Then
apt upgrade installs newer versions; apt full-upgrade does the same but will
remove old packages when needed.
sudo apt update
sudo apt full-upgrade
Example output
Reading package lists... Done
15 packages can be upgraded.
update then upgrade as a pair, regularly.
An unpatched service is the easiest way in; patching closes it before it is ever reached.
apt install · remove · purge · autoremove
install adds a package and its dependencies. remove uninstalls it but keeps
config; purge removes config too. autoremove cleans up dependencies nothing
needs anymore.
sudo apt purge nmap # remove a scanner + its config
sudo apt autoremove # then clean orphaned dependencies
nmap / zenmap (network scanning), netcat / ncat
(raw connections and reverse shells), steghide (hiding data inside images), and password
crackers or sniffers like john, hydra, and aircrack-ng. Unless a
tool has a clear reason to be there, apt purge it and then autoremove. Review
the removal list carefully; it is easy to uninstall something important.
Tracing a program to its package — which · dpkg -S · apt-cache search
Before you can remove a stray program — a game, a scanner, anything with no business on a workstation — you need its package name, which is not always the command you type. Three commands take you from "this thing is here" to "here is the package to purge."
which locates the program: it prints the full path of the executable that runs when you
type a command, found by searching your PATH.
which gnome-mahjongg
Example output
/usr/games/gnome-mahjongg
dpkg -S (search) names the installed package that owns that path — the answer to
"where did this come from?" Hand it the path, or nest which inside it.
dpkg -S /usr/games/gnome-mahjongg
dpkg -S $(which gnome-mahjongg) # same thing, in one step
Example output
gnome-mahjongg: /usr/games/gnome-mahjongg
The name left of the colon — gnome-mahjongg — is the package, so
sudo apt purge gnome-mahjongg removes it cleanly. To search the other direction — for a
package that is not installed yet — apt-cache search matches a keyword against
every available package's name and description.
apt-cache search mahjongg
apt-cache search nmap
Example output
gnome-mahjongg - classic Eastern tile game
nmap - The Network Mapper
which it to a path, dpkg -S the path to a package, then
sudo apt purge the package. For something with no obvious command — a game you only see in
the applications menu — dpkg -l | grep -i game lists installed packages by keyword, so you
can find it by name instead.
Package integrity — signatures & debsums
Patching assumes the packages you install are the ones the distribution actually published.
apt enforces that for you: every repository is signed, and apt verifies each package's
cryptographic signature against a set of trusted keys before it installs anything — a tampered
or spoofed package is refused. That signature check is the front line against supply-chain attacks like
the XZ backdoor.
Signatures protect a package in transit; debsums checks it after install. It
compares the files on disk against the checksums recorded when the package was built, so a system binary
an attacker has quietly replaced shows up as changed.
sudo apt install debsums # once
sudo debsums -c # list only files that fail their checksum
Example output — a flagged binary
/usr/bin/ssh
debsums -c prints nothing. A flagged system binary
— ssh, ls, sshd — is a serious finding: either a local change you
can explain, or a trojaned binary. Config files under /etc are expected to differ and can
be excluded with debsums -ce.
apt
system. The command line is faster once you know the package name, and it is the only option over a
plain SSH session.
8. Hardening: policy & PAM
This is where Linux security lives — and most of it is invisible to the graphical settings. Password aging rules, the authentication stack (PAM), account lockout, and kernel parameters are all edited as text. It is also where a single typo can lock everyone out, so the golden rule is: change it, test it in a second terminal, then close your editor.
/etc/login.defs
Sets the default password-aging policy for new accounts: how long a password lasts, how soon it can be changed, and when the warning starts.
Normal user shellgrep ^PASS /etc/login.defs
Example output
PASS_MAX_DAYS 90 # expire after 90 days
PASS_MIN_DAYS 1 # must wait 1 day before changing again
PASS_WARN_AGE 7 # warn 7 days before expiry
PASS_MAX_DAYS of 99999 means passwords
never expire — a common weak default. Tighten it to a sane maximum, set a minimum so users cannot cycle
back to an old password instantly, and keep a warning window.
chage — aging on existing accounts
login.defs only sets the policy for accounts created after you change it — it does
not touch anyone who already exists. To read or set aging on a current account, use chage
(change age): -l lists it, -M sets the maximum days, -m the
minimum, and -W the warning window.
sudo chage -l user1
Example output
Minimum number of days between password change : 0
Maximum number of days between password change : 99999
Number of days of warning before password expires : 7
Uses sudo
sudo chage -M 90 -m 1 -W 7 user1 # 90-day max, 1-day min, 7-day warning
login.defs alone is a classic half-done job: every
account that predates the change still reads 99999. Audit each real user with
chage -l and apply the policy to any that slipped through — exactly what the checklist's
"existing users have aging applied" step confirms.
PAM — the authentication stack
Pluggable Authentication Modules decide how login, sudo, su, and
passwd authenticate. Config lives in /etc/pam.d/, one rule per line, and each
rule is powerful and unforgiving: one wrong line can lock out every account, or silently accept any
password. Never edit it without a second root session open to undo the change — this is the exact
machinery the FIDO labs modify, which is why they insist on a break-glass account first.
common-* stack files, and how to
edit any of it safely — building all the way up to a preview of pam_u2f, the module the
FIDO Lab adds to this same auth stack so that logging in
requires touching a hardware key, not just a typed password.
/etc/pam.d/common-password
The pam_unix.so line here governs new passwords. Add minlen to require length
and remember to forbid reuse of recent passwords.
grep pam_unix /etc/pam.d/common-password
Example output
password [success=1 default=ignore] pam_unix.so obscure yescrypt minlen=10 remember=5
minlen=10 forces at least ten characters;
remember=5 blocks the last five passwords so users cannot cycle back to a favorite. Both
raise the cost of a guessed or cracked credential.
/etc/pam.d/common-auth — pam_faillock
pam_unix.so checks the password but does not count failures. pam_faillock.so
adds lockout: after too many wrong tries, the account is blocked for a while. The stack wraps the
existing auth line.
auth requisite pam_faillock.so preauth silent deny=5 unlock_time=900
auth [success=1 default=ignore] pam_unix.so
auth [default=die] pam_faillock.so authfail deny=5 unlock_time=900
auth required pam_faillock.so authsucc
deny=5— lock after 5 consecutive failures.unlock_time=900— unlock automatically after 15 minutes.- Check or clear counts with
faillock --user user1and--reset.
common-auth
can lock out everyone, including labadmin.
sysctl · /proc/sys
Kernel behavior is tunable through the /proc/sys tree, and made permanent in
/etc/sysctl.conf or /etc/sysctl.d/. sysctl --system reloads them.
cat /proc/sys/net/ipv4/tcp_syncookies
Example output
0 # SYN-flood protection is off
Uses sudo
echo 1 | sudo tee /proc/sys/net/ipv4/tcp_syncookies # on, until reboot
sudo sh -c 'echo 1 > /proc/sys/net/ipv4/tcp_syncookies' # same effect, redirect inside a root shell
/proc is lost on reboot. To make it
stick, set it in /etc/sysctl.d/ and reload with sudo sysctl --system.
tcp_syncookies=1 hardens against SYN-flood denial-of-service. Note that a bare
sudo echo 1 > … would fail — your shell opens the file as you, not root. Two
idioms get around this: pipe into sudo tee, or run the whole redirect inside a root shell
with sudo sh -c '…'.
9. Services & startup
A service is a program that runs in the background. The init system starts them at
boot and supervises them. Mint uses systemd, driven by systemctl; you
will still meet the older SysV names on other systems. Fewer running services means less to attack.
init & systemd
The kernel starts one first process — init, PID 1 — and every other process descends from
it. On Mint that is systemd. It starts services at boot, stops them at shutdown, and
adopts orphaned processes. (Older SysV init used numbered runlevels and scripts in
/etc/init.d/; systemd still understands them for compatibility.)
systemctl
One command controls services. enable/disable set whether a service starts
at boot; start/stop act now; status reports the current state.
systemctl status ssh
Example output
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
Active: active (running)
Uses sudo
sudo systemctl disable --now cups # stop printing service + keep it off at boot
systemctl list-unit-files --type=service --state=enabled
chkservice
An optional terminal UI that lists every service with its enabled/running state, so you can toggle them
interactively — a friendlier view than reading systemctl lists.
sudo apt install chkservice
sudo chkservice # [x] enabled > running = stopped
10. Processes & scheduled tasks
A process is a running program with a numeric PID. Knowing what is running, being able to stop it, and knowing what is scheduled to run later are core to spotting and evicting an intruder.
ps -ef · top
ps -ef (or ps aux) lists every process with its PID, parent PID (PPID), and
the user it runs as. top is the live, sorted-by-CPU view.
ps -ef | head -3
Example output
UID PID PPID CMD
root 1 0 /sbin/init splash
root 412 1 /usr/sbin/sshd -D
UID column shows what a process can do. A process
running as root that you do not recognize — or one owned by an account that should not exist — is worth
investigating. Note that the command name can be faked, so corroborate.
kill · killall — signals
You stop a process by sending it a signal. kill PID sends SIGTERM (a
polite "please quit"); if it ignores that, kill -SIGKILL PID forces it. killall name
targets by name; Ctrl+C interrupts the foreground program.
sudo kill 3709 # ask process 3709 to stop
sudo kill -SIGKILL 3709 # force it if it won't
/proc
On a compromised box, tools like ps can be replaced with liars (a rootkit trick). The
/proc filesystem reads straight from the kernel, so it is much harder to fake. Each PID has
a directory; /proc/1/exe points at the real executable behind PID 1.
sudo ls -l /proc/1/exe
Example output
lrwxrwxrwx 1 root root 0 Jun 12 /proc/1/exe -> /usr/lib/systemd/systemd
/proc, run known-good binaries from read-only media, and
when it matters, analyze the disk offline from a trusted machine.
cron · crontab · /etc/crontab
Scheduled jobs run on a timer via cron. The system schedule is /etc/crontab
and the drop-in directory /etc/cron.d/; each user also has a personal one edited with
crontab -e. A line's five time fields are: minute, hour, day-of-month, month, day-of-week.
cat /etc/crontab
Example output
# m h dom mon dow user command
17 * * * * root cd / && run-parts /etc/cron.hourly
/etc/crontab, /etc/cron.d/, and
each user's crontab -l for anything you did not put there — and check
systemctl list-timers too, since systemd timers are the modern equivalent
of a cron job and an equally common place to hide persistence.
11. Logs & auditing
Logs are the record of what happened. Mint keeps them in a systemd journal; the graphical Logs app browses it. For fine-grained tracking of who touched what, the audit daemon adds a second, tamper-resistant trail.
system logs — the journal & Logs app
The journal daemon collects log messages; the Logs application is its graphical viewer — think of it as Linux's Event Viewer. It filters by priority (Important shows the top severities), by category (Applications, System/kernel, Security, Hardware), and by date, and it searches by process, PID, or message text.
Uses sudosudo journalctl -p err -b # errors and worse, this boot
auditd · auditctl
Auditing is not on by default. Install the daemon, enable it, and it records security-relevant events you define — file access, config changes, authentication.
Uses sudosudo apt install auditd
sudo auditctl -e 1 # turn auditing on
12. Networking & exposure
Your network exposure is the sum of what is listening and what you allow in. Modern Linux uses the
ip and ss tools (the older ifconfig/netstat may not
be installed), and ufw is the friendly firewall.
ip addr · ip route
ip addr show lists interfaces with their addresses; ip route show lists how
packets leave the box. These replace the legacy ifconfig and route.
ip addr show eth0
ip route show
Example output
2: eth0: <BROADCAST,MULTICAST,UP> ...
inet 192.168.56.10/24 brd 192.168.56.255 scope global eth0
default via 192.168.56.1 dev eth0
192.168.56.0/24 dev eth0 proto kernel scope link
ss -A inet -anp
ss lists sockets — network connections and listening ports. The options: -A inet
IP sockets, -a all states, -n numeric (do not resolve names), -p
show the owning process. It replaces netstat.
sudo ss -A inet -anp
Example output
State Local Address:Port Peer Address:Port Process
LISTEN 127.0.0.1:3306 0.0.0.0:* mysqld # local only — safe
LISTEN 0.0.0.0:139 0.0.0.0:* smbd # any address — reachable from the network
ESTAB 192.168.56.10:55914 8.8.8.8:443 chromium # outbound to a remote host
127.0.0.1 is reachable only from the machine
itself; one on 0.0.0.0 is open to the whole network. Keep the list of network-facing
listeners to exactly what you need — any process or port you cannot identify should be treated as
suspicious.
ufw
The Uncomplicated Firewall. ufw enable turns it on, default deny incoming
blocks unsolicited inbound traffic, and allow opens exactly the services you intend.
sudo ufw enable
sudo ufw default deny incoming
sudo ufw allow ssh
sudo ufw status verbose
Example output
Status: active
Default: deny (incoming), allow (outgoing)
22/tcp ALLOW IN Anywhere
13. Remote access & SSH
SSH is the encrypted way into a machine from across the network — and because it is exposed, it is the
front door attackers knock on first. The server's behavior is set in /etc/ssh/sshd_config;
change a setting, test it, then reload the daemon. This is the same login path the FIDO labs harden, and
the one the XZ backdoor was built to subvert.
sshd_config — the daemon's policy
Read a setting, edit the file, then reload. The server config is
/etc/ssh/sshd_config (do not confuse it with ssh_config, the client's).
sshd -T prints the daemon's effective settings — the real answer after every
default and include is applied.
sudo sshd -T | grep -Ei 'permitrootlogin|passwordauthentication|pubkey'
Example output
permitrootlogin no
passwordauthentication no
pubkeyauthentication yes
Uses sudo
sudo sshd -t # test the config for syntax errors
sudo systemctl reload ssh # apply it without dropping live sessions
sshd -t before you reload — a broken
sshd_config can lock you out of a remote machine with no way back in. Keep a second session
open while you change it, exactly as with PAM.
The settings that matter
| Setting | Harden to | Why |
|---|---|---|
PermitRootLogin | no | Force admins to log in as themselves and escalate with sudo — attributable and logged. |
PasswordAuthentication | no | Requires a key; kills online password brute-force outright. |
PubkeyAuthentication | yes | Public-key login, the secure default. |
PermitEmptyPasswords | no | Obvious, but verify it is actually set. |
X11Forwarding | no | Shrink the surface unless you truly need forwarded GUIs. |
AllowUsers / AllowGroups | allow-list | Only the named users or groups may connect at all. |
PermitRootLogin no plus
PasswordAuthentication no is the two-line change that closes off the most common SSH
attacks. Everything reachable from the network should be an explicit allow-list, not a default-open.
Keys, not passwords
Key authentication replaces a guessable password with a keypair: the private key stays on your
client, and its public half goes into the server's ~/.ssh/authorized_keys. Only the
holder of the private key can log in.
ssh-keygen -t ed25519 -C "labadmin@mint" # create a modern keypair
ssh-copy-id labadmin@192.168.56.10 # install the public key on the server
chmod 600 and never leave your machine. This is the same idea the FIDO labs push one step
further: proof of possession instead of a shared secret. A hardware token takes it all the way,
because the private key physically cannot be copied off the device.