What would you like to learn?

Try PowerShell, networks, XSS, or Step 138

Browse the full curriculum →

Linux

Step 106. Linux Permissions Deep Dive — setuid, setgid, sticky bit

Step 106Estimated practice · 3 hours

Level 2 — Security Introduction and Attack Skill Basics | Difficulty ★★★☆☆ | Estimated time: 3 hours

Prerequisites: rwx, ownership, and sudo from Steps 23–24; your first encounter with setuid in Step 99 (Bandit 16–20).

  • What you need: a Linux terminal (Ubuntu/WSL) and one regular user account (if you don’t have one, you can substitute the system account nobody).
  • ⚠️ All exercises in this chapter are for your own lab and legal platforms only. Applying them to unauthorized systems is a crime.
  • Caution: all of today’s experiments happen in a practice folder under /tmp. We read system file permissions but never change them. Build the habit of deleting setuid experiment files when the exercise ends — scattering setuid files around is itself a vulnerability.

In Step 99 you met setuid for the first time — that strange bit that makes a file "run with its owner’s privileges." In Bandit it was a friendly ladder, but on a real server a misplaced setuid is an attacker’s elevator. Today you’ll create, find, and experiment with all three special bits — setuid, setgid, and the sticky bit — right up to abuse scenarios.

Privilege escalation is the subject that dominates the second half of an intrusion. Privileges are what separate "breaking in" from "taking over," and the three bits you’ll learn today are both the classics and the current reality of Linux privilege escalation. The climax of today’s experiments is a single scene — a regular user runs find, and a root shell pops out.


1. Learning Objectives

By the end of this chapter, you will be able to:

  • Explain how setuid, setgid, and the sticky bit each work in one sentence
  • Read s, S, t, and T in permission strings and convert them to numeric notation (e.g., 4755)
  • Enumerate every special-permission file on a system with find -perm
  • Consult GTFOBins to judge whether a setuid command can be abused
  • Reproduce privilege escalation with a setuid find, and explain bash’s privilege drop and the -p option

2. Background Knowledge — Today’s Tools and Concepts

Today’s Tools at a Glance

Category Details
Language/environment Linux shell (bash); experiments under /tmp
Today’s commands chmod u+s / g+s / +t, chmod 4755·2755·1777, find / -perm -4000, id, GTFOBins (web reference)
Concepts needed The 3 special permission bits, real UID vs effective UID (euid), GTFOBins, privilege drop
Today’s artifact Special-bit experiment records + an analysis memo of the system’s setuid list

2-1. The Fourth Digit — The Special Permission Bits

In Step 23 you learned that permissions are 9 switches (3 classes × 3 actions). In fact there are 12 switches. The remaining 3 are today’s protagonists.

Bit Number Where it goes Effect
setuid 4000 files runs with the file owner’s privileges
setgid 2000 files runs with the file group’s privileges / on a folder, files inside inherit the folder’s group
sticky 1000 folders inside it, you can only delete your own files

In numeric notation these three add one digit at the front. 4755 = setuid + 755, 1777 = sticky + 777.

2-2. setuid — Why Does This Even Exist?

Think of the passwd command. For a regular user to change their own password, they must modify /etc/shadow — but only root can write to that file. You can’t hand root to users, and you can’t make password changes impossible either.

The solution is setuid. With setuid on /usr/bin/passwd, the process borrows root privileges only for the moment a regular user runs it. The program modifies shadow only through its verified procedure and then exits — "legitimate delegation that lends you an identity" is the design intent.

Here’s the key term. A process carries two IDs — the real UID (who ran it) and the effective UID (euid, whose privileges it has right now). When a setuid program runs, its euid changes to the file’s owner. That’s why id output has a separate euid= field.

2-3. GTFOBins — An Encyclopedia of Legitimate Commands Living Double Lives

The danger of setuid lies in "what the program does while borrowing privileges." A program like passwd, which does only one thing, is relatively safe. But what happens if setuid lands on a legitimate command like find, vim, or less, which has a built-in feature for executing commands? You can spawn a shell with the borrowed root privileges.

GTFOBins (gtfobins.github.io) is an encyclopedia organized by command of "legitimate Linux commands that can be used for privilege escalation when misused via setuid and the like." An attacker who breaks into a server dumps the setuid list and cross-references it with this site — defenders must look at the same list to weed out unnecessary setuid bits.

2-4. The sticky bit — The Rule of the Public Square

/tmp is a square everyone writes in. With plain 777, anyone could delete anyone else’s files — chaos. The sticky bit adds one line of rules to this square: "write freely, delete only your own." The t at the very end of ls -ld /tmp is exactly that.


3. Follow Along

3-1. Attaching and Reading the Special Bits (measured)

Create an experiment folder and copy a real command to use as the test subject.

mkdir -p /tmp/perm-lab && cd /tmp/perm-lab
cp /bin/ls testbin
chmod u+s testbin
ls -l testbin

Output (measured 2026-09-09, Ubuntu 24.04 WSL):

-rwsr-xr-x 1 root root 142312 Sep  9 15:09 testbin

How to read it: the owner’s x slot has become an s — "execute permission is set, and so is setuid." Whoever runs this file, the process’s euid becomes the owner (root).

Let’s see setgid and sticky too (measured 2026-09-09):

chmod u-s testbin && chmod g+s testbin && ls -l testbin
mkdir shared && chmod 1777 shared && ls -ld shared
-rwxr-sr-x 1 root root 142312 Sep  9 15:09 testbin
drwxrwxrwt 2 root root 4096 Sep  9 15:09 shared

How to read it: setgid puts an s in the group’s x slot; sticky puts a t in the others’ x slot. You tell which bit is set by its position.

3-2. Uppercase S and T — Special Bits Without x (measured)

printf "x" > data.txt
chmod 4644 data.txt
ls -l data.txt

Output (measured 2026-09-09):

-rwSr--r-- 1 root root 1 Sep  9 15:09 data.txt

How to read it: the uppercase S means "setuid is set but execute permission (x) is not." This is the shape you get if you accidentally setuid a data file. The setuid on a file that can’t even execute does nothing, but to an eye scanning logs it reads as a sign of a configuration mistake. Lowercase/uppercase = presence/absence of x — that’s the rule for s/S and t/T.

3-3. Enumerating the System’s setuid Files (measured)

This is one of the first things an attacker does after breaking in. Let’s do exactly the same — with a defender’s eyes.

find / -perm -4000 -type f 2>/dev/null

Output (measured 2026-09-09, WSL — varies by distro and installed packages):

/usr/lib/openssh/ssh-keysign
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/polkit-1/polkit-agent-helper-1
/usr/bin/umount
/usr/bin/su
/usr/bin/sudo
/usr/bin/newgrp
/usr/bin/chsh
/usr/bin/chfn
/usr/bin/passwd
/usr/bin/mount
...

How to read it: the - in -perm -4000 means "entries with this bit turned on" (other bits don’t matter). There are two criteria for reading the list — ① does this program need root privileges (passwd, su, sudo, mount obviously do), ② is the command on GTFOBins. If ② applies without a ① reason, it’s a danger signal.

setgid works the same way (measured 2026-09-09, partial):

find /usr /bin /sbin -perm -2000 -type f 2>/dev/null
/usr/sbin/unix_chkpwd
/usr/bin/chage
/usr/bin/ssh-agent
...

3-4. setuid’s Real Effect — The Moment euid Changes (measured)

Let’s attach setuid to the id command and run it as a regular user. For the experiment we use the system’s built-in unprivileged account nobody.

cp /usr/bin/id id_suid && chmod u+s id_suid
su -s /bin/sh nobody -c "id"
su -s /bin/sh nobody -c "/tmp/perm-lab/id_suid"

Output (measured 2026-09-09):

uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
uid=65534(nobody) gid=65534(nogroup) euid=0(root) groups=65534(nogroup)

How to read it: the same person (nobody) typed the same command, but the second run has euid=0(root) added. The executor is unchanged, yet a borrowed privilege appeared. This one-line difference is the whole of setuid.

3-5. Reproducing the GTFOBins Pattern — Root Shell via setuid find (measured)

Now for today’s climax. Assume there’s a root-owned setuid find (= an administrator’s configuration mistake), and use GTFOBins’ canonical pattern as-is.

cp /usr/bin/find find_suid && chmod u+s find_suid
su -s /bin/sh nobody -c "/tmp/perm-lab/find_suid . -maxdepth 0 -exec /bin/sh -p -c 'id && whoami' ; -quit"

Output (measured 2026-09-09):

uid=65534(nobody) gid=65534(nogroup) euid=0(root) groups=65534(nogroup)
root

How to read it: find’s -exec is a legitimate feature that runs a command for each file found. An ordinary user (nobody) used find, and whoami printed root — you’ve just confirmed with your own hands that one line of configuration mistake leads directly to server takeover.

3-6. bash’s Privilege Drop and -p (measured)

But something’s odd. What happens if you remove -p from 3-5?

cp /bin/bash bash_suid && chmod u+s bash_suid
su -s /bin/sh nobody -c "/tmp/perm-lab/bash_suid -c id"
su -s /bin/sh nobody -c "/tmp/perm-lab/bash_suid -p -c id"

Output (measured 2026-09-09):

uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
uid=65534(nobody) gid=65534(nogroup) euid=0(root) groups=65534(nogroup)

How to read it: when the real UID and euid differ, bash drops its own privileges — a built-in safety device to prevent shell hijacking via setuid. -p (privileged) is the option that turns that drop off. That’s why 3-5’s pattern contains /bin/sh -p. For the same reason, some bypasses are blocked on recent distros, so if this pattern doesn’t work in the field, understanding the principle is enough.

3-7. The sticky bit — Confirming /tmp’s Rule (measured)

ls -ld /tmp

Output (measured 2026-09-09):

drwxrwxrwt 12 root root 4096 Sep  9 15:11 /tmp

How to read it: 1777 — read, write, and entry are open to everyone, but sticky (t) blocks only "deleting other people’s files." It’s the minimal rule that lets a public folder function as public. Our experiment folder (/tmp/perm-lab) has survived without being deleted by other users thanks to this rule.

3-8. Cleaning Up the Experiment

Delete the setuid files you made today once the experiment is over.

rm -rf /tmp/perm-lab

⚠️ rm -rf cannot be undone. Double-check the path before running it. And remember — if you ever find the exact file shape you just deleted (a setuid find) on a real server, that’s something to report as a vulnerability.


4. Missions & Exercises

Mission — Audit Your System’s Special Permissions

  1. Dump your system’s special-permission files with find / -perm -4000 and find / -perm -2000
  2. Classify each entry in the list by "does it have a legitimate reason?" — for anything you don’t recognize, search the command name on GTFOBins and check whether it has a "SUID" entry
  3. Perform the 3-5 root-shell reproduction yourself in /tmp/perm-lab and record the success screen (whoamiroot) in your write-up
  4. Write a "Special Permission Bits Summary" page in your wiki — one line each for how the three bits work, how to read them, and dangerous combinations

Exercises

Exercise 1. Convert the permission string -rwsr-x--- to numeric notation, and explain what happens when a group member executes this file.

Exercise 2. In find / -perm -4000, what does removing the - before -4000 (-perm 4000) make you find, and why does that become useless?

Exercise 3. Explain why bash drops its own privileges even when executed via setuid, and what the bypassing -p option means in an attack.

Exercise 4. If /tmp had no sticky bit (just plain 777), write one attack/accident scenario that would be possible.


Answers & completion criteria · expand/collapse

5. Model Answers & Completion Criteria

Mission Model Answer

A model format for the audit memo (based on the list measured 2026-09-09):

[legitimate] /usr/bin/passwd — delegation for modifying /etc/shadow
[legitimate] /usr/bin/su, /usr/bin/sudo — identity switching is their day job
[legitimate] /usr/bin/mount, /usr/bin/umount — delegation for filesystem work
[needs review] anything with a SUID entry on GTFOBins but no clear reason → consider removing

How to verify: ① are the outputs of both enumeration commands saved to files? ② is there one line each on why passwd, su, and sudo must be setuid? ③ in the 3-5 reproduction, did whoami print root (if not, check -p in 3-6)? ④ did you delete the experiment folder — ls /tmp/perm-lab should say "not found."

Exercise Answers

Answer 1. 4750. When a group member runs it, the process’s euid changes to the file’s owner, so it operates with the owner’s privileges. Others (o) have no permissions at all (---), so they can’t even execute it — the key combination is that setuid "restricts who it will lend to, using permissions."

Answer 2. Without the -, it finds only "files whose permissions are exactly 4000" — files with all rwx bits off, which almost never exist in practice. The - means "this bit is on, the rest don’t matter," so it’s essential for setuid enumeration.

Answer 3. When the real UID and euid differ, it means "someone is running with a borrowed identity," and opening an interactive shell in that state is privilege escalation itself, so bash lowers itself (confirmed in the 2026-09-09 measurement). -p is the option that disables that safety device, so in attack patterns it becomes "the switch that pins the borrowed privilege into a shell." That’s why -p keeps appearing in GTFOBins patterns.

Answer 4. Example: an attacker deletes a work file another user created in /tmp and swaps in a booby-trapped file with the same name, deceiving the program (or the next user) that reads it. A public folder where deletion and replacement are free is a classic stage for race condition attacks — the sticky bit is the device that closes that stage.

Completion Criteria Checklist

  • [ ] I can state how setuid, setgid, and sticky each work in one sentence
  • [ ] I can read the positions and uppercase/lowercase rules of s/S/t/T
  • [ ] I can interpret the front digit of four-digit numeric notation (e.g., 4755)
  • [ ] I can type find / -perm -4000 -type f 2>/dev/null from memory
  • [ ] I can explain the difference between uid and euid in id output
  • [ ] I can explain what GTFOBins is and why both attackers and defenders consult it
  • [ ] Mission: I completed the root-shell reproduction via setuid find and the system audit

6. Common Pitfalls & Fixes

Wall 1. find takes forever or floods you with permission errors

Symptom (Screen example):

find: '/proc/...': Permission denied

Cause: searching all of / buries the screen in errors from unreadable paths like /proc, and it’s slow.
Fix: discard errors with 2>/dev/null (in our measurements the results were hard to read without this option). On a large system, splitting the scope like find /usr /bin /sbin -perm -4000 also works.

Wall 2. I set setuid but privileges don’t rise

Symptom: even running the setuid file, id shows no euid.
Cause: ① the executor lacks execute permission (x) on the file, ② it’s a script file — the Linux kernel ignores setuid on scripts (only binaries work), ③ the filesystem is mounted with nosuid.
Fix: check s and x together with ls -l, and run experiments with a binary (a copy of /usr/bin/id) as in 3-4.

Wall 3. I typed the root-shell pattern but I’m still nobody

Symptom (measured 2026-09-09, with -p removed):

uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)

Cause: the shell (bash/dash) detected the setuid state and dropped its own privileges.
Fix: add -p, as in /bin/sh -p (see 3-6). If it still fails, that distro’s shell is stricter — it’s fine to move on with an understanding of the principle.

Wall 4. The numbers and symbols in -perm are confusing

Symptom: you can’t tell -4000, 4000, and /4000 apart.
Cause: find’s permission check has three modes — 4000 (exactly this), -4000 (this bit included), /4000 (any of these bits).
Fix: for setuid enumeration, just memorize -4000. Remember it as "minus means included."

Wall 5. You forget to clean up experiment files

Symptom: days later, setuid experiment files remain in /tmp or your home directory.
Cause: skipping the cleanup step of a hands-on chapter.
Fix: a habit starting today — when an experiment involving setuid ends, delete the file on the spot. On a real server, that file is the next intruder’s ladder.


7. Summary

Today’s Concepts

Concept One-line explanation
setuid (4000) A bit that borrows the file owner’s privileges at execution
setgid (2000) The file group’s privileges at execution / group inheritance on folders
sticky bit (1000) In a shared folder, only your own files can be deleted
euid A process’s "current privileges" ID — can differ from uid
GTFOBins An encyclopedia of legitimate commands abusable via setuid and the like
Privilege drop A safety device where a shell detects a setuid state and discards privileges itself (disabled with -p)
s/S distinction lowercase = x present, uppercase = x absent

Today’s Commands

Command What it does
chmod u+s file / chmod 4755 file Attach setuid
chmod g+s file / chmod +t folder Attach setgid / sticky
find / -perm -4000 -type f 2>/dev/null Enumerate setuid files
find / -perm -2000 -type f 2>/dev/null Enumerate setgid files
id Check uid and euid (borrowed privileges)
find . -exec /bin/sh -p ; -quit GTFOBins pattern — shell hijack via setuid find
ls -ld /tmp Check the sticky bit

An Instinct More Important Than Commands

setuid is a device where "legitimate delegation" and "fatal mistake" are a hair’s breadth apart. The criterion for telling them apart is simple — can the program do anything with the borrowed privileges (like find and vim), or does it do only one fixed job (like passwd)? From today, you’re set once the output of find / -perm -4000 starts reading as a checklist when you look at a system. Using the command an attacker types first after breaking in as the command a defender audits first — that offense and defense are looking at the same map is today’s final lesson.


Once every box is checked, Step 106 is complete.

ONE STEP FURTHER

Finished this lesson?

Check the completion criteria, then mark your progress.

Something wrong with this page or a link? Let us know.
Next