0x41p · OSCP Training Log

Linux PrivEsc — Abusing sudo, Weak Permissions & Custom Binaries

Theme of the day: Linux local privilege escalation — abusing sudo, weak file permissions, and custom binaries. Recurring lesson: the hint names the technique class — read it literally, then enumerate to confirm.

> Methodology notes only — generic examples and placeholder names throughout. No specific target, account, or solution details.

1. Know your ground — container awareness

Before picking a vector, confirm the environment and your current privilege:

cat /proc/1/cgroup            # paths showing /docker/<id> = Docker container
ls -la /.dockerenv            # exists in most Docker containers
systemd-detect-virt -c        # prints "docker"/"lxc" if containerized
id; whoami                    # are you already root? what groups?

Key takeaway: run id and check for a container first. If you're already uid=0 inside a container, "abusing sudo" is moot and the objective shifts to host breakout (docker.sock, dangerous capabilities). Privilege + environment decide the whole approach.

2. Abusing sudo — sudo -l and Baron Samedit

sudo -l is the command that drives every sudo privesc. Patterns to read for: NOPASSWD entries, (root) run-as, env_keep/LD_PRELOAD, wildcards/influençable scripts, and old sudo versions.

The trap: when sudo -l reports "user may not run sudo", people abandon sudo entirely. But CVE-2021-3156 (Baron Samedit) is a heap overflow in argument parsing that triggers before the sudoers check — so it works for any local user with no sudo rights and no password.

sudo --version | head -1     # vulnerable: <= 1.8.31p2 and 1.9.0–1.9.5p1
# non-destructive vuln test — heap error/segfault = vulnerable, clean usage: = patched
sudoedit -s '\' $(python3 -c 'print("A"*1000)')

Other sudo CVEs to keep in pocket: CVE-2019-14287 (sudo -u#-1), CVE-2023-22809 (sudoedit -s / EDITOR arg injection).

Key takeaway: a sudo version string is itself an exploit primitive. "May not run sudo" ≠ "sudo is safe."

3. Weak file permissions

When a box hints "look for file permissions," hunt writable things root cares about:

# Files writable by you that are OWNED BY ROOT — the money shot
find / -uid 0 -writable -type f 2>/dev/null | grep -vE '^/(proc|sys)'
# World-writable files and directories
find / -perm -0002 -type f 2>/dev/null
find / -perm -0002 -type d 2>/dev/null
# Crown-jewel targets, checked explicitly
ls -l /etc/passwd /etc/shadow /etc/sudoers /etc/sudoers.d/* /etc/crontab

Payoffs: writable /etc/passwd → UID-0 user; writable /etc/shadow → overwrite root's hash; readable /etc/shadow → crack offline; writable /etc/sudoers → grant yourself NOPASSWD; writable root-owned cron/service script → reverse shell or chmod +s /bin/bash.

Key takeaway: "file permissions" hints almost always mean writable + privileged-owner. Lead with -uid 0 -writable, not a blind world-writable sweep.

4. Custom binary / custom shell

When the hint points at a custom privileged binary (GTFOBins won't list custom binaries), reverse it for a shell:

# confirm privilege
sudo -l ; find / -perm -4000 -type f 2>/dev/null ; ls -l <binary>
# enumerate flags
<binary> --help ; <binary> -h ; <binary>          # bare run may drop into a menu
# reverse it when help is thin
strings <binary> | less                            # hardcoded paths, system()/popen(), hidden flags
ltrace <binary> 2>&1 | less                        # watch system()/exec*()/fopen()
strace -f <binary> 2>&1 | grep -E 'exec|open'      # what it really runs/reads

Three jackpots: a system() call on a bare command name → PATH hijack (export PATH=/tmp:$PATH); a flag taking a command/filename you control; a shell it launches. Restricted/custom-shell escapes: injection chars (; | $() \\ &&) in input fields; pager/editor-as-root escapes (vi → :!/bin/sh, less/man → !/bin/sh, awk 'BEGIN{system("/bin/sh")}').

Key takeaway: for custom binaries, strings/ltrace is your GTFOBins. A bare command name in a system() call = PATH hijack nearly every time.

Cross-cutting themes