~$ skillshelf
← OverTheWire Bandit

Bandit 21 → 22: it already ran

banditlinuxcronpermissions

Something is scheduled to run on this box on a timer, as a user I’m not. The level says to go read the cron config and see what it does. The trap is thinking the job is something you have to trigger. It isn’t — it already ran, a minute ago, and it’ll run again before you finish reading its source.

the goal

A program is running automatically at regular intervals from cron, the time-based job scheduler. Look in /etc/cron.d/ for the configuration and see what command is being executed.

the approach

/etc/cron.d/ holds one file per scheduled job. Most are other wargames sharing the host, or OS housekeeping. The one that matters names my target:

cat /etc/cron.d/cronjob_bandit22
@reboot   bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
* * * * * bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null

Two lines, not duplicates. These are /etc/cron.d/ files, so they use the system crontab format — six fields, and the extra one before the command is the user to run as: bandit22. @reboot fires once when cron starts at boot; * * * * * is five wildcards, which reads as “every minute, every hour, every day — always.” So this script runs as bandit22, once a minute, forever.

The script is readable, so I read it:

cat /usr/bin/cronjob_bandit22.sh
#!/bin/bash
chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv

Three lines. It cats bandit22’s own password into a fixed file in /tmp, then chmod 644s that file so everyone can read it. /etc/bandit_pass/bandit22 is the real password and I can’t touch it — but this script, running as bandit22, can, and it copies it somewhere I can.

The obvious move is to run it, and every version of that is closed:

./cronjob_bandit22.sh
line 3: /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv: Permission denied

Denied, because ./ runs it as bandit21, who can’t write that file. Pasting the script’s three lines into the shell does the same thing for the same reason — that also runs them as me. So does logging in as the target:

ssh bandit22@bandit.labs.overthewire.org
Permission denied, please try again.

All three are the same move wearing different hats: trying to be the user who runs the job. That’s not the level. The job already has a user, and it isn’t me.

The unlock is that the script has already run, as bandit22, within the last minute — so the password is sitting in that /tmp file right now, and line 2 already made it world-readable for me. I don’t run anything. I read what cron already produced.

One snag: /tmp won’t list.

ls /tmp
ls: cannot open directory '.': Permission denied

Which doesn’t matter — the filename is hardcoded in the script I just read, so the exact name is already in hand:

cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
<redacted>

the takeaway

The lesson here isn’t cron syntax, it’s reading versus running. A scheduled job means the work is already being done, on a timer, by someone with the rights to do it. My job was to read the result it leaves behind — not to reproduce the action myself, which I never had the permission to do anyway.

Two things I’m keeping:

  • ./script, pasting a script’s lines into your shell, and ssh-ing in as the target are all the same move — they run the commands as you. If the whole point is that a different user has a permission you don’t, none of them can work. Stop trying to become the actor; go find what the actor left.
  • A hardcoded /tmp filename is a feature, not a leak. /tmp here won’t even let me list it, so the only way to the file is to have read the script that names it. Reading the config is the level.