Privilege Escalation · beginner · ~10 min

Privilege escalation: the enumeration-first mindset

**What you will learn** - Define privilege escalation and distinguish **vertical** (higher privilege) from **horizontal** (sideways to a peer account) movement. - Explain why privesc is **enumeration-driven** — you hunt misconfigurations, you rarely write an exploit. - Recognise the one recurring pattern behind nearly every technique: *high-privilege code trusting something a low-privilege user controls.* - Read your own identity and privileges safely (`id`, `whoami /priv`, `sudo -l`) and reason about what each result means. - Apply the inverse **defensive** view: least privilege, safe trust boundaries, and the logs that reveal escalation attempts. - Set up a legal, isolated lab and follow an authorization checklist before running any check.

Overview

Security objective. The asset we are protecting is the privilege boundary on a host — the line between a normal, low-privileged user and a powerful account like root on Linux or SYSTEM/Administrator on Windows. The threat is an attacker (or malware, or a compromised service) who already has a low-privileged foothold and wants to cross that line to read every file, install persistence, or pivot deeper into the network. In this lesson you learn to detect and reason about the misconfigurations that let that happen — and, more importantly, how a defender prevents and logs them.

What privilege escalation is. It turns limited access into control. You start as an ordinary user and end as an administrator. It is almost always the step right after an initial foothold: a phished login, a web-app bug, a reused password. The foothold gets you in; escalation gets you power.

Two directions.

  • Vertical — gaining a higher privilege level (user → root/SYSTEM). This is the classic goal.
  • Horizontal — moving sideways to another account at the same level (e.g. from alice to bob), often to reach data or to set up a later vertical jump.

Why it is enumeration-first. Most escalation is not a memory-corruption exploit. It is finding a misconfiguration — a writable file a root job trusts, a sudo rule that is too broad, a password left in a script. So the dominant skill is systematic enumeration: methodically asking who am I, what do I control, what trusts it?

How this connects to your prereqs. You already studied Files, directories, and permissions — read/write/execute bits, owners, and the setuid bit. Privesc is that knowledge weaponised for review: a world-writable file owned by root is no longer trivia, it is a finding. You also studied The Windows privilege model: UAC and tokens — integrity levels, access tokens, and privileges like SeImpersonatePrivilege. Privesc is where those tokens become the thing you enumerate. This lesson is the map; the next lesson, Linux privesc: sudo and SUID binaries, is the first concrete technique.

Why it matters

In authorized professional work — penetration tests, red-team engagements, and internal security reviews — privilege escalation is the near-universal second phase. A report that says "we phished one user" is far less impactful than "...and from that single low-privileged user we reached Domain Admin because of three misconfigurations." Escalation is what demonstrates real business risk to a client.

It matters because it is overwhelmingly about configuration, not exploits. That is good news for defenders: the same misconfigurations that let an attacker escalate are findable and fixable before anyone attacks. A blue-team engineer who understands the enumeration mindset can run the same checks and remediate the writable service binary, tighten the sudo rule, and delete the plaintext credential — closing the door proactively.

One lens ties the dozens of techniques together: high-privilege code that trusts attacker-controlled input. Once you carry that lens, the techniques stop feeling like a random checklist and become instances of a single idea — which is exactly what makes both attacking (in a lab) and defending (in production) systematic instead of lucky.

Finally, this is a foundational skill for hardening, compliance, and incident response. When an incident responder asks "how did they get from a web shell to root?", the answer is almost always a privesc path that should have been caught by a review.

Core concepts

This lesson is conceptual: it builds the mental model the rest of the track hangs on. Each concept below has a definition, a plain explanation, how it works, when it applies, and a pitfall.

1. Privilege escalation

  • Definition. Gaining rights beyond those originally granted to your account or process.
  • Plain explanation. You logged in as a limited user; you end up acting as an administrator.
  • How it works. You find a resource that a privileged context (a root cron job, a SYSTEM service, a setuid binary) reads, executes, or trusts — and that you can influence. Feeding it your own input causes the privileged context to act on your behalf.
  • When / when-not. It applies once you already have some access (a foothold). It is not the initial break-in and it is not usually about exploiting a bug in the CPU or kernel — those exist but are the minority.
  • Pitfall. Assuming you need a fancy 0-day. In practice a chmod mistake beats an exploit almost every time.

2. Vertical vs horizontal

Vertical Horizontal
Direction Up a privilege level Sideways, same level
Example userroot/SYSTEM alicebob
Typical goal Full control of the host Reach another user's data, or stage a later vertical jump
Detection signal A low-priv account suddenly running root actions Access to files/sessions of an unrelated peer
  • Pitfall. Treating horizontal movement as "not real" progress. Reaching a peer account often unlocks the vertical path (that peer may be in the sudo group).

3. Enumeration-first mindset

  • Definition. Systematically inventorying identity, permissions, running privileged code, and stored secrets before trying anything.
  • How it works. You answer a fixed set of questions, from cheapest to most invasive: Who am I? What can I write that something privileged reads? What runs as root/SYSTEM and can I influence it? What credentials are lying around?
  • When / when-not. Always first. Skipping enumeration to "try an exploit" wastes time and is noisy.
  • Pitfall. Running an automated helper (LinPEAS/WinPEAS, conceptually) and pasting its output without understanding why each flagged item is dangerous. The tool finds candidates; you decide which are real.

4. The universal pattern (and its inverse defense)

  • Definition. Every technique is one shape of: a low-privileged user controls something a high-privileged context trusts.
  • Inverse defense. Two rules cancel almost all of it: (a) least privilege — give every account and service the minimum rights it needs; (b) never trust writable or low-integrity input inside a high-privilege process — validate paths, pin absolute binary locations, drop privileges early.
  • Pitfall. Believing a vulnerability scanner "passing" proves a host is secure. Scanners miss logic and config nuances; a clean scan is evidence, not a guarantee. Nothing is ever "completely secure."

Threat model

                 TRUST BOUNDARY (privilege line)
   LOW PRIVILEGE  |  HIGH PRIVILEGE
  ---------------- | -------------------------------
   Attacker as     |   root cron job
   local user  --->|   SYSTEM service       <-- ASSETS: root/SYSTEM
   (the foothold)  |   setuid-root binary       control of the host,
        |          |   scheduled task           all files, persistence
        |          |
   ENTRY POINTS the low side controls that the high side trusts:
    * a world-writable file the root job reads/executes
    * a script on a PATH the root job searches
    * an over-broad sudo rule ( user may run X as root )
    * a credential left in a config/history/env variable
    * a service binary the user can overwrite

   Attack  = supply malicious input across the boundary.
   Defense = least privilege + validate/refuse untrusted input
             + LOG every privileged action and every denial.

Knowledge check.

  1. What asset is protected here? (The privilege boundary — the ability to become root/SYSTEM and control the host.)
  2. Where is the trust boundary? (The line between the low-privileged user and any high-privileged context that reads their input.)
  3. Which insecure assumption causes most privesc? (That input coming from a low-privileged, writable, or low-integrity source is safe to trust inside a privileged process.)
  4. Which logs would reveal an attempt? (sudo/auth logs, process-execution auditing, and file-integrity alerts on privileged binaries — covered in the safety section.)
  5. Why run these checks only in an authorized lab? (Enumerating and exploiting privilege boundaries on a system you do not own or lack written permission for is illegal and unethical, even when "just looking.")

Syntax notes

The core of enumeration is a handful of read-only, lab-safe identity commands. None of these change the system; they answer "who am I and what am I trusted to do?" Run them only in your own lab.

# Linux — read-only identity checks
id                 # your UID/GID and group memberships (are you in sudo/adm/docker?)
whoami             # current username
sudo -l            # what may THIS user run via sudo (prompts for YOUR password)
groups             # group list, shorthand for the groups in id
:: Windows (PowerShell / cmd) — read-only identity checks
whoami /priv       # your token's privileges (look for SeImpersonatePrivilege etc.)
whoami /groups     # group SIDs and integrity level
whoami /user       # your account SID

Annotated: sudo -l is the single most valuable Linux enumeration command — it prints exactly which commands your account may run as another user, revealing over-broad rules. On Windows, whoami /priv reveals dangerous enabled privileges. Reading this output is enumeration; acting on a finding is the actual escalation and must stay inside the lab.

Lesson

Privilege escalation turns a limited foothold — a low-privileged user — into a powerful one: root on Linux, SYSTEM or admin on Windows. It is almost always the step right after gaining initial access.

Vertical vs horizontal

  • Vertical: gain higher privileges (user → root/SYSTEM). This is the main goal.
  • Horizontal: move to another account at the same level. This is often done to reach data or to set up a later vertical escalation.

Enumeration, not exploits

Most privilege escalation is not a memory-corruption exploit. It is finding a misconfiguration — for example:

  • a writable file that a root process trusts,
  • a sudo rule that is too broad,
  • a stored credential left on disk.

So the dominant skill is systematic enumeration. Work through questions like these:

  • Who am I? What groups and privileges do I have? (id, whoami /priv)
  • What can I write that something privileged reads or executes?
  • What runs as root or SYSTEM, and can I influence it?
  • What credentials are lying around?

Automated helpers (LinPEAS and WinPEAS, conceptually) sweep these checks for you. But understanding why each check is dangerous is what lets you act on the output.

The recurring pattern

Every technique in this track is one shape of the same idea: a low-privileged user controls something a high-privileged context trusts. Find that, and you escalate.

The defenses are the inverse:

  • apply least privilege, and
  • never trust writable or low-integrity inputs inside a high-privilege process.

Code examples

The example is conceptual (this is a concept-track lesson): a tiny, self-contained lab misconfiguration showing the universal pattern, then the secure fix, then a verification that the fix rejects the abuse and still allows legitimate use.

(1) WARNING: intentionally vulnerable — use only in a local, isolated, authorized lab. Do not deploy.

A root-owned scheduled job that trusts a world-writable script. This is the classic "high-privilege code trusts a low-privilege-controlled resource."

# Setup, as root, INSIDE A THROWAWAY LAB VM/CONTAINER ONLY:
cat >/opt/report.sh <<'EOF'
#!/bin/sh
echo "nightly report: $(date)" >>/var/log/report.log
EOF
chmod 0777 /opt/report.sh          # <-- THE BUG: world-writable

# root runs it on a schedule (simulate the trusted, privileged execution):
#   * * * * * root /opt/report.sh

# A low-privileged lab user can now rewrite what root will execute:
echo 'id > /tmp/who_ran_me' >/opt/report.sh   # legal ONLY in your own lab
# On the next run, root executes attacker-controlled content.

Why it works: the file is executed by root but writable by everyone. The privilege line is crossed because the trusted resource is attacker-controllable.

(2) SECURE fix

Remove the write capability of low-privileged users over anything a privileged context executes, and keep ownership with root.

# As root:
chown root:root /opt/report.sh
chmod 0755 /opt/report.sh          # owner root may write; others read+exec only
# Store privileged scripts outside world-writable dirs; never 0777.

(3) VERIFY — prove the fix rejects abuse and accepts legitimate use

# REJECTS bad input: a normal user can no longer tamper.
$ whoami
labuser
$ echo 'evil' >>/opt/report.sh
sh: /opt/report.sh: Permission denied      # expected: write is refused

# ACCEPTS good input: root's scheduled run still works.
$ sudo /opt/report.sh && tail -n1 /var/log/report.log
nightly report: <current date/time>        # expected: legitimate run succeeds

# Audit check: confirm no privileged file is world-writable.
$ find /opt /usr/local -perm -0002 -type f -ls   # expect: no output

Expected outcome. After the fix, the tamper attempt is denied (Permission denied), the legitimate scheduled task still runs, and the audit find returns nothing — the misconfiguration is closed and verified.

Line by line

Walkthrough of the lab example above.

  1. cat >/opt/report.sh <<'EOF' ... EOF — root creates a small script the scheduler will run nightly. This is the privileged context.
  2. chmod 0777 /opt/report.sh — the defect. 0777 = rwxrwxrwx: any user can write the file. The trusted resource is now low-privilege-controlled.
  3. The cron line * * * * * root /opt/report.sh — root executes the file on a schedule. Root never re-checks who last edited it; it simply trusts the path.
  4. echo 'id > /tmp/who_ran_me' >/opt/report.sh — the low-privileged lab user overwrites the file. Nothing has escalated yet; the payload is just sitting there.
  5. Next scheduled run — root executes the replaced content as root. The output of id proves the code ran with root's UID. The privilege boundary was crossed.

Trace of the security-relevant state:

Step Actor File writable by Who runs it Effective privilege of the payload
1–2 root everyone (0777) scheduler as root — (no payload yet)
4 labuser everyone payload staged
5 scheduler everyone root root — escalation

After the fix:

  1. chmod 0755rwxr-xr-x: only the owner (root) may write. Others may read and execute but not modify.
  2. Verify steplabuser's write returns Permission denied (abuse rejected); sudo /opt/report.sh still logs a report (legitimate use accepted); the find -perm -0002 audit returns nothing (no world-writable privileged files remain). The same pattern — remove the low-privileged control over the trusted resource — is the fix for the entire category.

Common mistakes

Real mistakes learners and teams make, and how to correct them.

  1. WRONG: jumping straight to exploits / kernel 0-days. Why wrong: wastes time, is noisy, and misses the 90% of paths that are pure misconfiguration. Corrected: enumerate first (id, sudo -l, whoami /priv), map what you control, then act. Recognise/prevent: if you have not run identity checks yet, you are guessing.

  2. WRONG: dismissing horizontal movement as unimportant. Why wrong: the peer account you ignored may be the one in the sudo or docker group — it is your vertical path. Corrected: treat every reachable account as a possible stepping stone. Recognise/prevent: always check the groups/privileges of any account you reach.

  3. WRONG: trusting automated-scanner output blindly. Why wrong: LinPEAS/WinPEAS flag candidates; not every yellow line is exploitable, and a clean run does not prove security. Corrected: understand why each check matters and confirm findings manually. Recognise/prevent: if you cannot explain why an item is a risk, you cannot report it responsibly.

  4. WRONG (defender): fixing one world-writable file and calling it done. Why wrong: the pattern usually repeats across cron, services, and PATH. Corrected: sweep the whole class (find ... -perm -0002, audit sudoers, review service binary permissions). Recognise/prevent: remediate the category, then re-verify with an audit command.

  5. WRONG: testing on a system you do not own "just to look." Why wrong: unauthorized enumeration of privilege boundaries is illegal and unethical, even without a payload. Corrected: use your own lab VM/container or a sanctioned CTF; get written authorization for any real target. Recognise/prevent: no scope document, no testing.

Debugging tips

When a lab check or a fix does not behave as expected:

  • sudo -l asks for a password you do not know. That is expected — it needs your password. In a lab, log in as a user whose password you set. Never attempt to bypass it on a real system.
  • whoami /priv shows a privilege but it is Disabled. Disabled ≠ absent, but it also is not automatically usable. Note the state; do not assume an enabled capability.
  • Your "vulnerable" cron demo never fires. Check the crontab is installed for the right user (crontab -l / /etc/crontab), the script is executable, and the schedule field is valid. Add a line that appends a timestamp to a log so you can confirm it runs at all.
  • The fix seems applied but abuse still works. Re-check effective permissions with ls -l and namei -l /opt/report.sh (a writable parent directory also lets a user replace the file even if the file itself is 0755). Directory permissions are a common blind spot.
  • find -perm -0002 returns things you did not expect. That is the point — investigate each. Confirm whether a privileged context executes them.

Questions to ask when a privesc reasoning task fails. Who executes the resource, and with what privilege? Who can write the resource or its parent directory? Does the privileged code use an absolute path or search PATH? Did I verify the fix both rejects abuse and accepts legitimate use?

Memory safety

Security & safety — detection and logging. This lesson has no C memory concerns; the equivalent discipline is making escalation visible and auditable.

What to log for every privileged action or denial:

  • Timestamp (UTC, from a trusted clock).
  • Source identity — the real UID/user, session, and source host/IP.
  • Resource — the exact file/command/service touched (absolute path).
  • Result — success or failure, and the security decision (allowed / denied and why).
  • Correlation id — a session or request id so a foothold can be tied to the later escalation across log sources.

Concrete sources that detect the patterns in this lesson:

  • sudo/auth.log (or journalctl _COMM=sudo) — every sudo invocation, including denials and "command not allowed" events.
  • Process-execution auditing — Linux auditd execve rules, or Windows Event ID 4688 (process creation) and Sysmon Event ID 1.
  • File-integrity monitoring on privileged binaries/scripts (e.g. AIDE, or Windows FIM) — alerts when a root-run script changes.
  • Windows Security log 4672 (special privileges assigned to new logon) and 4673/4674 (privileged service/operation) for token abuse.

NEVER log: passwords, the contents of a sudo password prompt, session cookies/tokens, private keys, full credential files, or unnecessary PII. Log that an event happened and its decision — not the secret involved.

Which events signal abuse: a low-privileged account suddenly running many sudo commands or hitting repeated "not allowed" denials; a root-executed script whose hash changed outside a deployment; a normal user acquiring an unusual token privilege; execution of a shell from a service account.

How false positives arise: legitimate admins genuinely use sudo; deployment pipelines legitimately change scripts (so integrity alerts must be correlated with change tickets); backup or monitoring agents run as root by design. Tune by baselining normal behaviour and correlating with the correlation id and change records before escalating an alert — an alert is a lead, not a verdict.

Real-world uses

Authorized use case. During a sanctioned internal penetration test, a tester lands a low-privileged web-app foothold. Enumeration (id, sudo -l, a review of cron and service permissions) reveals a root cron job running a world-writable script — exactly the pattern in this lesson. The tester documents the path, demonstrates impact once in scope, and the report recommends chown root:root + chmod 0755 plus a file-integrity monitor. The blue team fixes it and re-tests. This is privesc used to drive hardening, not damage.

Professional best-practice habits:

  • Validation / safe trust: privileged code must validate inputs and never execute writable-by-others resources or search a user-controlled PATH.
  • Least privilege: run services under dedicated low-privileged accounts; grant narrow, specific sudo rules, never ALL.
  • Secure defaults: scripts 0755 and root-owned; secrets in a vault, never in config/history/env; drop privileges as early as possible.
  • Logging: audit sudo, process execution, and integrity of privileged binaries; alert on the abuse signals above.
  • Error handling: fail closed — a privileged process that cannot verify its input should refuse to run, not run anyway.

Beginner vs advanced.

Beginner Advanced
Focus Read identity safely; recognise the one pattern; fix a single world-writable file and verify Chain enumeration findings into a full path; automate category-wide audits; tune detection to cut false positives
Tooling id, sudo -l, whoami /priv, ls -l auditd/Sysmon rules, FIM, sudoers policy review, CI checks that reject 0777 in privileged paths
Mindset "What do I control that something trusts?" "How do I make every crossing of the privilege boundary logged, least-privileged, and verified?"

Practice tasks

All tasks are lab-only — run them on your own throwaway VM/container or a sanctioned CTF. Authorization checklist before starting: (1) you own the machine or have written permission; (2) it is isolated (no production data, no third-party network); (3) you have a snapshot to restore; (4) you know the cleanup steps. Every task ends by remediating and verifying, never by leaving a hole open. Cleanup/reset: revert the VM snapshot, or undo each change (restore original permissions, remove test files, clear test cron entries) and re-run the audit command to confirm a clean state.

Beginner 1 — Read your identity.

  • Objective: map your own privileges without changing anything.
  • Requirements: in your lab, run id, groups, and sudo -l (Linux) or whoami /priv and whoami /groups (Windows). Write, for each output line, one sentence on why a defender would care.
  • Constraints: read-only commands only.
  • Hints: look for membership in sudo/docker/adm, or an enabled SeImpersonatePrivilege.
  • Concepts: enumeration-first, identity.

Beginner 2 — Classify the direction.

  • Objective: practice vertical vs horizontal.
  • Requirements: write five short scenarios (e.g. "labuser gains root", "alice reads bob's mail") and label each vertical or horizontal, with one line on how it could enable a later vertical jump.
  • Constraints: no commands; reasoning only.
  • Hints: a horizontal move often unlocks vertical.
  • Concepts: vertical/horizontal, chaining.

Intermediate 1 — Reproduce and fix the world-writable pattern.

  • Objective: build the lab example, then remediate.
  • Requirements: create a root-owned 0777 script (as in the lesson), confirm a low-priv user can rewrite it, then fix with chown/chmod. Input/output: before the fix a low-priv write succeeds; after, it returns Permission denied.
  • Constraints: isolated VM only; snapshot first.
  • Hints: also check the parent directory permissions.
  • Concepts: universal pattern, least privilege, mitigation verification.
  • Defensive conclusion: prove the fix rejects the tamper and still allows the legitimate run, then run find -perm -0002 -type f to confirm no siblings remain.

Intermediate 2 — Detection.

  • Objective: make the abuse visible.
  • Requirements: enable logging (e.g. tail auth.log/journalctl _COMM=sudo, or add an auditd execve rule / enable Windows 4688) and repeat the intermediate-1 scenario; capture the log lines that reveal the tamper and the privileged execution.
  • Constraints: log the event and decision, never any secret.
  • Hints: correlate the low-priv write with the later root execution.
  • Concepts: detection, logging fields, correlation id.
  • Defensive conclusion: state which single log line you would alert on and one plausible false positive for it.

Challenge — Mini enumeration report.

  • Objective: combine everything into a short professional finding.
  • Requirements: on your lab VM, run a systematic sweep (identity, sudo -l, world-writable privileged files, a stored-credential grep of your own test config). Pick the single most impactful misconfiguration and write a finding: title, severity (justified by exploitability/access/impact — not automatically critical), affected component, preconditions, safe reproduction, evidence, impact, remediation, retest.
  • Constraints: placeholders for any secret (API_KEY=<development-placeholder>); lab-only.
  • Hints: severity is not "critical by default" — justify it.
  • Concepts: enumeration, reporting template, mitigation verification.
  • Defensive conclusion: end with the exact remediation commands and the audit command that proves the fix, then reset the lab snapshot.

Summary

Main concepts. Privilege escalation converts a low-privileged foothold into root/SYSTEM. It comes in two directions — vertical (up a level) and horizontal (sideways to a peer, often to unlock a later vertical jump). It is overwhelmingly enumeration-driven: you hunt misconfigurations, you rarely write an exploit. Every technique is one shape of a single pattern — a low-privileged user controls something a high-privileged context trusts — and its inverse is the defense: least privilege plus never trusting writable/low-integrity input in a privileged process.

Key commands (read-only enumeration). id, groups, sudo -l (Linux); whoami /priv, whoami /groups (Windows). The remediation pattern is chown root:root + a non-world-writable mode, verified with find -perm -0002.

Common mistakes. Reaching for exploits before enumerating; dismissing horizontal moves; trusting scanner output blindly (a clean scan does not prove security, and decoding is not verifying); fixing one file instead of the whole category; and — most importantly — testing anything outside a system you own or are authorized to test.

What to remember. Enumerate first. Find what you control that something privileged trusts. Fix by removing that control and applying least privilege. Verify the fix both rejects abuse and accepts legitimate use, and log every privileged action and denial. Nothing is ever "completely secure" — only better-hardened and better-monitored.

Practice with these exercises