•
Bash with no letters
2 minute read •
I recently did a challenge on PicoCTF (U2Fuc0FscGhhCg 🐶) and I had to explore some bash trickery to solve it. I learned a few that are worth noting here for future me or future you.
The challenge starts in a limited shell in which you can only enter numbers and some special characters.
Excluded characters were: a-zA-Z\
Got to find a way to enter letters without using letters! Or so I thought.
Substring expansion
My first idea was to capture any error message into a variable and to use that to get the letters I needed.
Once I got l and s, I could capture the output of ls and then cat the flag file.
# capture the error message with redirection of stderr into stdout
_1=
# excellent! we now have access to an l and an s
# index 0 is `b`, index 1 is `a`, and so on
# ls
# capture output of ls to reference the folder name
_3=
# ls folder
# capture output of ls folder
_4=
# cat folder/flag.txt
That’s very ugly to say the least. But I got the flag anyway! 🚩
That was the long way, though. Turns out there was a very simple way to get the flag. Not sure why I didn’t think of it earlier!
Path expansion, wildcards & pattern matching
Using only * and ?, we can list files in directories or call some binaries.
To make this work, we would need something more specific since we’re matching more than one binary. But it could work.
An even easier way is to use only path exapansion and wildcards.
I noticed ~ was working as expected:
Now we know where the flag is located!
Subshell
The command substitution
$(cat file)can be replaced by the equivalent but faster$(< file). Source
Turns out we don’t even need letters!
Reading the flag is as simple as sending the path pattern as an input redirect in the subshell. Since there’s the return 0 string at the beginning of the flag file, we need to quote the command substitution to get the whole string.
There you have it, folks, that’s bash in all its beauty! 😅