I am on Debian 9 (Stretch). I have a deploy user where I've set the shell to /bin/rbash. Here is the line from /etc/passwd:


If I am the root user, and I run su - deploy or su -l deploy, then it starts rbash (echo $SHELL # => /bin/rbash), but commands are not being restricted:

~$ echo $SHELL  
~$ cd /tmp
/tmp$ echo asdf > /tmp/file
/tmp$ /bin/cat /tmp/file  
# (Should not allow any commands with a slash)

If I just run su deploy:

~$ echo $SHELL
~$ cd /tmp
rbash: cd: restricted
~$ /bin/cat /etc/passwd
rbash: /bin/cat: restricted: cannot specify `/' in command names

Why doesn't rbash apply any restrictions if this is a login shell?

  • echo $SHELL just lists the login shell, but that doesn't prove that you're running it. What does echo $0 $- report? – muru Jun 3 at 9:41
  • Thanks @muru, the output of echo $0 $- is: -su himBHs – ndbroadbent Jun 3 at 9:57
  • Ah interesting, if I run su deploy, then the output of echo $- is himrBHs, where the r is the --restricted flag. I wonder why it's not being added for su - deploy? – ndbroadbent Jun 3 at 10:00

From the Bash manual:

If Bash is started with the name rbash, or the --restricted or -r option is supplied at invocation, the shell becomes restricted.

Now, "started with the name" means that $0, or the zeroth element of argv is that name. But when su starts it as a login shell, it sets the name to -su. And the -r option wasn't used either, so neither method of starting a restricted shell was used when su starts a login shell.

It should still take effect for other, proper means of login (such as SSH, or login(1) over a TTY).

  • Hello, thanks for your answer! I think you might be right! I've discovered something else in the su man page, in the --shell section that talks about the shell that will be invoked. It says that shell will be chosen first from the -s or --shell flag, then if --preserve-environment is used, it uses the existing $SHELL variable. Finally it looks at the entry in /etc/passwd. So I've been able to force the restricted bash shell by running: su -s /bin/rbash deploy. (And su -p -s /bin/rbash deploy, since I want the same env.) – ndbroadbent Jun 3 at 10:14
  • But for some reason this still doesn't work if I run su -l -s /bin/rbash deploy. The bash flags are still himBHs, and it's not a restricted shell. If I run echo $0, I still get: "-su". – ndbroadbent Jun 3 at 10:17
  • The other problem is that su -s /bin/rbash deploy doesn't load the deploy user's .bashrc or .profile, which is why I wanted the -l flag. – ndbroadbent Jun 3 at 10:19
  • I also tried exec -a rbash su -l deploy to change the name in $0, but that didn't seem to do anything. echo $0 still shows: -su. But I finally realized that I can pass an argument to bash by using --. My final command is: exec su -l -p -s /bin/rbash deploy -- -r. Now echo $0 shows returns -su, but I'm explicitly passing the --restricted flag (-r), so echo $- shows hirBHs. (And I checked that I can't turn it off with set +r.) (exec is also a great idea because an attacker can't just exit to get back to the root user.) – ndbroadbent Jun 3 at 10:32
  • One last thing! This command was still trying to load the .bashrc for the root user, because $HOME was not being reset properly (even though the su man page says that it should be.) So I needed to explicitly set the $HOME variable so that it loads the correct .bashrc: export HOME="/home/deploy" && exec su -l -p -s /bin/rbash deploy -- -r. Thanks for your help! – ndbroadbent Jun 3 at 10:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.