How to Bypass User Shell in su Command When Target Shell Is Missing


2 views

When executing commands via su as another user, the system attempts to spawn the target user's configured shell (from /etc/passwd) before running the command. This becomes problematic when:


su - -c 'mkdir bin' user1
# Fails with: su: /usr/bin/ksh: No such file or directory

Option 1: Force bash/sh Execution

Override the shell temporarily using env:


su - user1 -s /bin/sh -c 'mkdir bin'
# Or for more complex commands:
su - user1 -s /bin/bash -c 'export PATH=/usr/local/bin:$PATH; mkdir bin'

Option 2: Direct Command Execution

Use sudo (if available) to bypass shell entirely:


sudo -u user1 mkdir bin

Option 3: Permanent Fix

Change the user's shell configuration:


# As root:
chsh -s /bin/bash user1
# Or edit /etc/passwd directly

The su command behavior stems from Linux PAM (Pluggable Authentication Modules) configuration. You can examine the exact flow using:


strace -f su - user1 -c "echo test" 2>&1 | grep execve

This reveals the exact shell execution attempt before command processing.

For automation scripts, consider these robust approaches:


# Using sudo with full path
sudo -u user1 /bin/bash -c 'mkdir -p /home/user1/bin'

# Or with environment preservation
sudo -u user1 -i -- env PATH=$PATH /bin/sh -c 'complex_command'

Remember that some systems may have SELinux or AppArmor policies that affect shell switching behavior.

For system administrators managing multiple users:


# Batch change shells for users with missing shells
getent passwd | grep '/usr/bin/ksh' | cut -d: -f1 | while read user; do
  chsh -s /bin/bash "$user"
done

When executing commands with su while specifying another user, the system attempts to use the target user's default shell (as defined in /etc/passwd). This becomes problematic when:

  • The specified shell isn't installed (ksh in your case)
  • The shell exists but isn't functional
  • You need to bypass shell-specific initialization files

The most straightforward method is using the --shell parameter (GNU coreutils implementation):

su - --shell=/bin/bash -c 'mkdir bin' user1

This forces the system to use /bin/bash regardless of the user's default shell setting.

If you have sudo privileges, this completely bypasses the shell issue:

sudo -u user1 mkdir bin

Benefits include:

  • No shell switching occurs
  • Cleaner process inheritance
  • Better audit logging

For systems without GNU coreutils:

su - user1 -c 'exec /bin/bash -c "mkdir bin"'

For recurring issues, consider modifying /etc/default/su (Debian) or equivalent:

# Force fallback shell
ALWAYS_SET_PATH=yes
SHELL=/bin/bash

When debugging shell issues:

# Verify user's shell setting
getent passwd user1 | cut -d: -f7

# Test shell availability
which ksh bash sh

Be aware that shell forcing may:

  • Bypass security profiles (like rbash restrictions)
  • Skip important environment initialization
  • Affect expected PATH resolution