Josh Wright and I were working on a project recently which involved a target machine with a really restricted shell environment. I'm not talking about a mere rbash with some limits on the executables we could access, but instead a shell so restricted we could not run any binaries at all, save for the shell itself. No ls... no cat... no netcat... we could access very little. It was some sort of ghastly chroot specter.
Still, Josh and I wanted to explore the target machine as much as we could given these shell restrictions. Of course we could have tried escaping our restricted shell (as Doug Stilwell describes in more detail here) and even doing privilege escalation, but before that, we wanted to just look around. Thankfully, we had many shell built-in capabilities we could rely on.
For the uninitiated, shell built-ins are features of the shell that don't rely on separate binaries in the system. For example, in bash, commands such as alias, printf, and echo are built-ins, which the shell can do itself, without calling a separate program. While some of these built-ins also have a binary of the same name (/bin/echo for example), your shell can rely on the built-in independently from the binary. Indeed, it can perform the task even if the binary isn't available. Turns out, you can do a whole lot with these shell built-ins.
A handy list of bash built-ins is available here, and can be quite an inspiration when faced with a task like that before Josh and me.
We started by looking around in the file system, using the following well-known trick as our rough "ls" equivalent:
$ echo * file.txt
We then wanted to look at the contents of file.txt, so we ran:
$ while read line; do echo "$line"; done < file.txt Hello World! This is a nice file. Happy Holidays!
We then wanted to search through a file to find a specific string, rather like grep:
$ while read line; do if [[ $line == *"nice"* ]]; then echo $line; fi; done < ./file.txt This is a nice file.
Want a count of the number of lines in a file (rather like wc -l)? Use something like:
$ i=0; while read line; do i=$(($i+1)); done < ./file.txt; echo $i 3
Want your UID number? You should try:
$ echo $UID 1024
Wanna do a whoami? If you have access to the world-readable /etc/passwd, you could build on what we saw above with:
$ while read line; do if [[ $line == *":x:$UID:"* ]]; then echo ${line%%:*}; fi; done < /etc/passwd nobody
Those are just a few of the useful items we performed with built-ins. Got any more you'd like to share? Please do provide them in the comments below.
Thanks!
— Ed Skoudis & Josh Wright