learn/phase-2/p2-w6/lesson 04
Milestone 6 · lesson 4

File Permissions in Depth: Octal, SUID, SGID & the Sticky Bit

Hands-on. Read and set every permission bit, including the special ones that drive privilege escalation.
Lab: The Unexpected SUID

Enumerate SUID binaries, spot the one that doesn't belong, and read the flag inside it.

What you'll learn

  • Convert fluently between symbolic (rwx) and octal (755) permissions.
  • Set permissions with chmod (both notations) and change ownership with chown and chgrp.
  • Explain what read, write and execute actually mean on a directory, which is not what most beginners assume.
  • Recognise and set the three special bits: SUID, SGID and the sticky bit, and read them in ls output.
  • Explain why a root-owned SUID binary is a classic privilege-escalation target, and why /tmp has a sticky bit.

File Permissions in Depth: Octal, SUID, SGID & the Sticky Bit

The last lesson introduced rwx. That's the surface. This lesson is the whole iceberg, the notation shortcuts, ownership, what the bits really mean on directories, and the three special bits that are the difference between a locked-down box and a root shell. If you plan to do privilege escalation later, this is the lesson it all rests on.

Recap: the three triads

-    rwx    r-x    r--
type owner  group  others

Every file has three sets of read / write / execute bits: one for the owner, one for the file's group, one for everyone else (others). The leading character is the type (- file, d directory, l symlink).

Two ways to write the same thing: symbolic vs octal

Each triad is really three bits, and three bits make a number from 0 to 7. That's why permissions are so often written as three octal digits:

SymbolicBitsOctalMeaning
---0000nothing
--x0011execute
-w-0102write
-wx0113write + execute
r--1004read
r-x1015read + execute
rw-1106read + write
rwx1117everything

The trick: r = 4, w = 2, x = 1, add them up per triad.

rwx r-x r-x   ->   7 5 5   ->   chmod 755
rw- r-- ---   ->   6 4 0   ->   chmod 640
rwx --- ---   ->   7 0 0   ->   chmod 700

Setting permissions with chmod

Octal sets all three triads at once:

chmod 644 notes.md     # rw-r--r--  (a typical file)
chmod 600 id_rsa       # rw-------  (a private key: owner only)
chmod 755 script.sh    # rwxr-xr-x  (a program everyone may run)

Symbolic changes bits relative to what's there, which is often clearer:

chmod u+x script.sh    # add execute for the user (owner)
chmod go-w file        # remove write from group and others
chmod a=r file         # set everyone to read-only (a = all)

u = user/owner, g = group, o = others, a = all; + adds, - removes, = sets exactly.

Ownership: chown and chgrp

Permissions are meaningless without knowing who owns the file.

chown analyst report.txt          # change the owner
chown analyst:staff report.txt    # change owner AND group at once
chgrp staff report.txt            # change only the group

Changing ownership needs root. This matters for security: if you can change the owner of a file, the permission bits no longer protect it from you.

The bit everyone gets wrong: x on a directory

On a file, x means "run it as a program". On a directory it means something completely different: the right to enter it (cd in) and reach the files inside by name.

  • r on a directory: you can list its names (ls).
  • x on a directory: you can traverse into it and access a file if you know its name.
  • w on a directory: you can create and delete files in it (note: deleting a file is a write to the directory, not the file, which is exactly what the sticky bit below reins in).

So a directory with r but no x lets you see the names but touch nothing; x but no r lets you open a known path but not browse. Beginners lose hours to this.

The special bits

Beyond the nine rwx bits there is a fourth, leading octal digit holding three special bits. They are where permissions stop being bookkeeping and start being a security frontier.

SUID , Set User ID (octal 4000)

A file with SUID set runs with the privileges of its owner, not the user who launched it. You see it as an s in the owner's execute position:

-rwsr-xr-x 1 root root /usr/bin/passwd
   ^ here

/usr/bin/passwd is owned by root and SUID, so when you run it, it briefly acts as root, just enough to write your new password into /etc/shadow (a file you can't touch directly). That's the legitimate use.

The dangerous use: any root-owned SUID binary that can run other commands, read files, or spawn a shell hands a normal user root. Enumerating them is one of the first things an attacker does:

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

If an unusual binary (say find, vim, nmap, or a custom script) shows up in that list owned by root, it's very likely a privilege-escalation path. We come back to this in the Privilege Escalation and GTFOBins lessons.

A capital S (instead of s) means the SUID bit is set but the underlying execute bit is not, usually a misconfiguration.

SGID , Set Group ID (octal 2000)

SGID is the same idea for the group, and it does two things depending on where it sits:

  • On a file: the program runs with the file's group privileges. Shows as s in the group's execute position (-rwxr-sr-x).
  • On a directory: new files created inside inherit the directory's group instead of the creator's. This is how shared project folders keep everything under one group.
find / -perm -2000 -type f 2>/dev/null   # enumerate SGID binaries

The sticky bit (octal 1000)

The sticky bit only matters on directories. In a world-writable shared directory it restricts deletion: only the owner of a file (or root) may delete or rename it, even though everyone can write to the directory. You see it as a t in the others' execute position:

drwxrwxrwt 10 root root /tmp
        ^ here

/tmp is the classic example: everyone needs to create temp files there, but without the sticky bit any user could delete any other user's files. A capital T means the sticky bit is set without the underlying x.

Setting the special bits

Prepend the fourth octal digit (SUID = 4, SGID = 2, sticky = 1), or use symbolic form:

chmod 4755 prog     # SUID + rwxr-xr-x   (chmod u+s prog)
chmod 2755 dir      # SGID + rwxr-xr-x   (chmod g+s dir)
chmod 1777 shared   # sticky + rwxrwxrwx (chmod +t shared)

umask: the default that decides new files

You never run chmod when you create a file, yet it still comes out with some permissions. Those defaults are decided by the umask, a mask that removes permission bits from a starting point.

The system starts from a base:

  • 0666 for new files (rw-rw-rw-, files never get execute by default)
  • 0777 for new directories (rwxrwxrwx)

...then strips out whatever bits the umask has set. The exact rule is a bitwise AND with the inverse of the mask:

final = base & ~umask

Try it yourself, type a umask and watch the new-file and new-directory permissions update:

umask calculator
octal, e.g. 022
file0666& ~0022=0644-rw-r--r--
dir0777& ~0022=0755drwxr-xr-x

The mask removes bits from the base (0666 for files, 0777 for directories). Try 000 to see a world-writable result, or 077 to lock new files down to the owner only.

Worked example, a mask of 0000. First check the current value (two ways to read it):

$ umask
0000
$ umask -S
u=rwx,g=rwx,o=rwx

A mask of 0000 removes nothing, so for a new file:

0666 & ~0000
= 0666

So the new file becomes:

-rw-rw-rw-

...world-writable, exactly as observed. That's a dangerous default and a real finding on a hardened box.

Worked example, a mask of 0022 (the common, safer default):

0666 & ~0022 = 0644   ->  -rw-r--r--   (files)
0777 & ~0022 = 0755   ->  rwxr-xr-x    (directories)

The 022 strips the write bit from group and others, so new files stay readable by all but writable only by you. Set it with umask 022.

Why this matters

Permissions are the most basic access-control mechanism on the box, and they are where a huge share of real findings live: a world-writable script that root runs on a timer, a private key left 644, a forgotten SUID binary, a config readable by others. Reading these bits fluently, and knowing which ones are dangerous, is the difference between walking past a root shell and noticing it.

Try it (terminal)

  1. ls -l /usr/bin/passwd , spot the SUID s.
  2. find / -perm -4000 -type f 2>/dev/null , enumerate every SUID binary.
  3. ls -ld /tmp , find the sticky bit t.
  4. chmod 640 notes.md then ls -l notes.md , watch the mode change to rw-r-----.
  5. chmod u+s,g+s script.sh , set SUID and SGID symbolically, then read the result.

Check your understanding

6 questions

Type an answer and press Check. Grading is keyword-based and forgiving, so short answers are fine.

  1. 1

    Write the octal mode that means: owner read+write+execute, group read+execute, others read+execute.

  2. 2

    You see -rwsr-xr-x on /usr/bin/passwd. What is the s where the owner's execute bit should be, and what does it do?

  3. 3

    On a directory, what does the execute (x) bit actually grant?

  4. 4

    /tmp shows as drwxrwxrwt. What is the trailing t, and what problem does it solve?

  5. 5

    Write the find command that lists every SUID binary on the system (a standard privesc enumeration step).

  6. 6

    Which command makes analyst the owner and staff the group of report.txt in one go?