cybersecurity · intermediate · ~15 min

Flag a $PATH entry that is writable by anyone but root

The classic PATH-hijack audit primitive.

Challenge

Flag a directory that is unsafe to have in a privileged user's $PATH — a writable PATH directory is a privilege-escalation primitive, and this audit is the cheap defence.

Task

Implement int dir_is_path_hazard(unsigned mode, int owner_uid) that returns 1 if the directory is dangerous, else 0.

Input

  • mode: the directory's POSIX st_mode bits the grader passes. Relevant bits: 0002 = world-writable, 0020 = group-writable.
  • owner_uid: the directory's owner uid (0 = root).

Output

Returns int: 1 if the directory is world-writable, OR group-writable and not owned by root (owner_uid != 0); else 0.

Example

dir_is_path_hazard(0777, 1000)   ->   1   (world-writable)
dir_is_path_hazard(0775, 1000)   ->   1   (group-writable, non-root owner)
dir_is_path_hazard(0775, 0)      ->   0   (group-writable but root-owned)
dir_is_path_hazard(0755, 1000)   ->   0

Edge cases

  • A world-writable directory is always a hazard, regardless of owner.
  • The sticky bit (01000) and setuid bit do not change the answer here.

Rules

  • Pure bit math on the mode flags; treat mode as octal.

Why this matters

A writable directory in $PATH is a privilege-escalation primitive: drop a binary called ls, wait for a privileged user. The audit step is the cheap defence.

Input format

An unsigned mode (POSIX st_mode bits) and an int owner_uid.

Output format

An int: 1 if the directory is a PATH hazard, else 0.

Constraints

World-writable -> hazard; group-writable + non-root owner -> hazard. Pure bit math.

Starter code

int dir_is_path_hazard(unsigned mode, int owner_uid) { /* TODO */ (void)mode; (void)owner_uid; return 0; }

Common mistakes

Treating mode as decimal. Forgetting the group-writable+non-root case.

Edge cases to handle

Sticky bit set (01000): irrelevant here. Setuid bit: irrelevant here.

Complexity

O(1).

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.