~/tutorials/036-up-on-linux.md
036: Up, on Linux
You have a shell as an ordinary user. The question that decides the engagement: what on this box will run something for you, with rights you do not have?
Privilege escalation is a census before it is an exploit. Enumerate everything, fire nothing, until the whole picture is on the table. The ordering is the skill. Firing first is how you burn the one shot a misconfiguration gives you.
The census
Run these from the shell you hold, on the box you hold it on. The lesson before this one is where that shell came from:
$ sudo -l
$ find / -perm -4000 -type f 2>/dev/null
$ getcap -r / 2>/dev/null
$ crontab -l
$ ls -la /etc/cron*
$ cat /etc/passwd | grep -v nologin
Six commands, six different ways a box hands out privilege. sudo -l is first, because it answers what you are already allowed to do, and the answer is regularly more than the administrator thinks. Setuid binaries run with their owner's rights, and half the list is usually legitimate software with a known exception. Capabilities split root into pieces, so a binary can hold one dangerous capability without being root. Cron runs scripts on a schedule, and the script's permissions are the question.
Read the answers as sentences. An empty sudo answer on a box without sudo installed is a different sentence than a refusal, and which sudo tells them apart. A setuid list of one binary and a setuid list of forty are both normal somewhere, and which is which is a fact about how the box was built, not a score.
The misconfiguration, not the bug
Most practice escalation is a misconfiguration. A setuid binary that should not be. A cron script writable by your user. A sudo rule with a wildcard where a path should be. The box was configured by a person with other things to do.
That is why the census comes first. Each finding is a sentence in a story about how the machine was actually built, and the exploit is the last sentence, not the first.
Two worked misconfigurations, the shapes the tier builds its practice from. A sudoers line that hands an ordinary user one binary, /usr/bin/find, no password. A root cron entry that runs /opt/scripts/backup.sh every five minutes, in a directory where that script is writable by everyone. Both are one line of configuration. Both are root.
The firing order
- Read every census answer. Understand what each binary is, not just what it is called.
- Rank by what you can verify. GTFOBins, at gtfo bins dot github dot io, documents what a setuid binary or a sudo entry actually grants, binary by binary. Check it, then verify locally.
- Fire one. The quietest one that gets you root.
The find route, on the box where sudo allows it, is one line:
$ sudo find . -exec /bin/sh -c id \;
The answer comes back uid=0, because find runs as root and -exec runs what you give it. That is the whole exploit. The cron route is quieter and slower: append one line to the writable script, a line that copies bash somewhere and marks it setuid, wait five minutes for root's schedule to fire it, and run the copy.
Reveal the answer
The cron payload line, what to append to the writable script:
$ echo 'cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash' >> /opt/scripts/backup.sh
The chmod +s is the setuid bit, the same bit the census hunted in binaries, now applied to a shell you own. When the cron entry fires as root, the copy lands root owned and setuid. Running it needs one flag, because bash drops privileges otherwise:
$ /tmp/rootbash -p
$ id
The id answers uid=0(root). The -p is privileged mode, and without it bash notices it is setuid and steps down, which is the one refusal in the route. Close the route the way the box should have, chmod 644 on the script and the sudoers line deleted, and the census comes back clean.
Run this against Metasploitable, and then against a clean Ubuntu you configured yourself. The clean box teaches the other half: what an ordinary census looks like, so the abnormal one reads abnormal to you.
Try it
- Run the census on your lab target. Write every finding down with its why. The shell is the one lesson 034 gave you, and the box is the one the apparatus page the known entry stood up.
- Rank them. Fire the best one. The two worked misconfigurations above are the shapes to build if your box offers nothing, one sudoers line and one writable cron script, both planted by you on a box you own.
- Then fix the box. Close every route you used, and run the census again until it comes back clean. The closing commands are behind the reveal below, because the closing is also an exercise, and the exercise is the point of this step.
Reveal the answer
Closing is the same one line per route that opening was. The sudoers line is a file under /etc/sudoers.d, and deleting the file deletes the grant:
# rm /etc/sudoers.d/student
The writable script keeps existing, because the cron entry may be legitimate work. What closes the route is the permission, not the file:
# chmod 644 /opt/scripts/backup.sh
If the firing left a setuid shell behind, that goes too:
# rm /tmp/rootbash
Run as root or with your remaining privilege, one line each. Then the receipt, from the seat you started in: sudo -l as the ordinary user answers that a password is required, because there is no passwordless grant left to list. The ls on the script reads -rw-r--r-- root root. The setuid census carries no copy of bash. That is a box that comes back clean, and the three answers are what clean looks like from the outside, which is the only side a defender ever sees.
You have not learned an escalation until you have closed one.