Bandit 32 → 33: the shell that uppercases you
“After all this git stuff, it’s time for another escape” is the entire level
page, and it’s accurate. Log in and there’s no bash — there’s something that
takes whatever I type, shifts it to uppercase, and runs that. ls goes out as
LS and comes back not found. Every command I know is lowercase, and so is
every path I need.
the goal
After all this
gitstuff, it’s time for another escape. Good luck!
Two commands listed, sh and man. That’s the whole page.
the approach
what’s actually running
One file in home, uppershell:
file uppershell
uppershell: setuid ELF 32-bit LSB executable, dynamically linked,
interpreter /lib/ld-linux.so.2, not stripped
Two things worth reading off that. setuid — it runs with elevated privileges rather than mine, which is how it gets to sit between me and my own keyboard no matter who logs in. And ELF executable — it’s compiled, so there’s no script to open and read. That route was closed before I tried it.
strings uppershell
Plenty of output, and it confirmed the suspicion: the thing spawns a shell and shifts input to uppercase on the way through. Good as confirmation, useless as a lever. I now knew exactly how the trap worked and was no closer to being outside it.
the actual problem
Stated plainly: every character I type arrives uppercased. Not a permissions
problem, not a missing binary. The password lives at /etc/bandit_pass/bandit33
and there is no way to type that path.
So the question stops being “what command do I run” and becomes “where is there lowercase text that didn’t come from my keyboard?”
$0
$0 is the name of the current shell. Two characters, neither with a case to
shift, so it goes through the filter untouched — and what it expands to is a
lowercase string the shell was already holding.
Typing it gave me a working shell. From inside that:
echo $0
sh
echo $0 | cat
sh
Lowercase both times, and the second one is the confirmation: the trap mangles
what I type, not what flows through a pipe. $0 was never typed — it’s a
lowercase string already in memory, and it survives.
reading the file
With a shell that would accept a command, I put the read through $0 itself, so
the command text came from the shell rather than from the keyboard:
$0 -c 'cat /etc/bandit_pass/bandit33'
Password, redacted here as <password>.
the takeaway
A filter only controls the channel it sits on. The uppercaser owns my
keystrokes and nothing else. $0 held sh in lowercase before I ever logged in,
so reflecting it back hands me a string the filter never touched. When input is
being mangled, stop hunting for a command you can type and start looking for
values the program is already holding.
Two smaller ones:
file first, every time. One command said setuid, compiled, not a script —
which killed “read the source” immediately and told me the binary runs as someone
other than me. Same setuid idea as 26 → 27, except here it’s the thing standing
in my way rather than the thing helping me.
strings confirms; it doesn’t solve. It explained the mechanism precisely
and moved me nowhere. Understanding how a trap works and having a lever against
it are different things, and it’s easy to spend a while mistaking the first for
the second.
That’s the end of the trail. Level 33 is the last one — the official page for bandit34 says it doesn’t exist yet — so this is where the chapter stops.