Granting remote SSH access to third-party contractors, software auditors, or automated data ingestion pipelines introduces significant lateral movement risks on Linux servers. A standard shell environment allows users to traverse directory structures, inspect environment variables, read sensitive world-readable configuration files in /etc, and execute non-essential administrative utilities. When full containerization or virtual machines impose excessive overhead for simple interactive file transfers or constrained administrative tasks, Linux systems administrators configure restricted shells and chroot jails.
Ubuntu provides two robust, complementary mechanisms for isolating users at the operating system level: Restricted Bash (rbash) and OpenSSH ChrootDirectory jails. While rbash restricts command execution and environment path modifications within the shell interpreter itself, OpenSSH chroot incarceration prevents the user’s filesystem root from viewing or accessing any directory outside their designated sandbox. This comprehensive technical guide explains how restricted shells operate, how to configure rbash, how to build secure OpenSSH chroot directories, and how to verify jail containment against common privilege-escalation escapes.
Security Capabilities and Constraints of Restricted Bash (rbash)
Restricted Bash is an invocation mode of the standard GNU Bash binary (invoked via /bin/rbash or bash -r). When operating in restricted mode, Bash enforces several strict behavioural constraints designed to prevent user lateral movement:
| Restricted Operation | Shell Behaviour Under rbash | Security Benefit |
|---|---|---|
Directory Changing (cd) |
The cd built-in command is disabled; returns rbash: cd: restricted. |
Locks the user inside their initial home or assigned working directory. |
| Path Environment Modifications | Modifying, unsetting, or reassigning $PATH, $SHELL, $BASH_ENV, or $ENV is blocked. |
Prevents overriding the execution search path to execute unapproved binaries. |
Slash Invocations (/) |
Command names containing a forward slash cannot be executed (e.g., /bin/cat fails). |
Forces all binary execution through pre-approved symlinks placed in the user’s bin/ directory. |
Redirections (>, >>, <>) |
Output redirection operators are disabled. | Prevents overwriting system files or creating malicious executables via shell pipes. |
| Command Execution via exec | The exec built-in cannot be used to replace the shell process with an unconstrained shell. |
Prevents spawning secondary subshells that evade restrictions. |
Step-by-Step: Provisioning a Restricted rbash User Account
Follow these operational steps on Ubuntu Server to establish a dedicated restricted user with access restricted strictly to curated commands (such as ls, cat, and nano):
1. Register the Restricted Shell and Create the User
# Verify that /bin/rbash exists (symlinked to /bin/bash)
which rbash || sudo ln -s /bin/bash /bin/rbash
# Ensure /bin/rbash is registered in the list of valid login shells
grep -qxF "/bin/rbash" /etc/shells || echo "/bin/rbash" | sudo tee -a /etc/shells
# Create the dedicated restricted user account
sudo adduser --shell /bin/rbash restricteduser
2. Build a Curated Binaries Directory
Because rbash blocks forward slashes, users can only execute binaries residing in directories defined within their immutable PATH variable. We create an isolated bin folder inside the user’s home directory containing selective symbolic links:
# Create the isolated binary directory owned by root to prevent tampering
sudo mkdir -p /home/restricteduser/bin
sudo chown root:root /home/restricteduser/bin
sudo chmod 755 /home/restricteduser/bin
# Symlink only explicitly approved binaries into the user's bin directory
sudo ln -s /bin/ls /home/restricteduser/bin/ls
sudo ln -s /bin/cat /home/restricteduser/bin/cat
sudo ln -s /usr/bin/nano /home/restricteduser/bin/nano
sudo ln -s /usr/bin/uptime /home/restricteduser/bin/uptime
3. Lock Down User Profile and Path Definitions
To ensure the user cannot alter their environment variables upon login, lock down their .profile and .bashrc configurations with root ownership and read-only permissions:
# Overwrite .profile to enforce PATH strictly to the curated bin directory
sudo tee /home/restricteduser/.profile << 'EOF'
# Restrict PATH to custom bin
PATH=$HOME/bin
export PATH
EOF
# Lock user profile files so the restricted user cannot modify them
sudo chown root:root /home/restricteduser/.profile /home/restricteduser/.bashrc
sudo chmod 644 /home/restricteduser/.profile /home/restricteduser/.bashrc
Step-by-Step: Building an OpenSSH Chroot Jail for SFTP and SSH
While rbash limits shell commands, it does not prevent the user from reading system-wide configurations or world-readable files across the real root filesystem (such as /etc/passwd). For absolute containment, combine OpenSSH with a kernel-enforced ChrootDirectory jail.
1. Create the Chroot Directory Hierarchy
OpenSSH enforces strict security requirements on chroot jail directories: every component of the pathname leading up to the chroot root must be owned by root and must not be writable by any other user or group.
# Establish the chroot base jail directory
sudo mkdir -p /jail/sftpuser/uploads
# Configure mandatory root ownership on the jail root
sudo chown root:root /jail/sftpuser
sudo chmod 755 /jail/sftpuser
# Grant the user full ownership of their internal uploads folder exclusively
sudo chown sftpuser:sftpuser /jail/sftpuser/uploads
sudo chmod 750 /jail/sftpuser/uploads
2. Configure OpenSSH Daemon Rules (sshd_config)
Edit the OpenSSH daemon configuration file to intercept incoming sessions for the restricted user group and bind them to the chroot environment:
# Edit the SSH daemon configuration
sudo nano /etc/ssh/sshd_config.d/chroot.conf
Append the following configuration directive:
# Match rule for chrooted users or group
Match User sftpuser
ChrootDirectory /jail/sftpuser
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
PasswordAuthentication yes
3. Validate Syntax and Restart OpenSSH
# Test configuration syntax for errors before restarting
sudo sshd -t
# Reload OpenSSH daemon service
sudo systemctl reload ssh
Testing and Validating Jail Integrity
Audit your security barriers from a remote terminal to verify that neither command escapes nor unauthorized file operations succeed:
- Verify rbash Path Traversal Blockage: Authenticate as
restricteduserand attempt to runcd ..or/bin/bash. The shell will reject both attempts withrbash: restricted: cannot specify `/' in command names. - Verify OpenSSH Jail Incarceration: Connect via SFTP using
sftp sftpuser@server_ip. Executepwdand verify that the root directory is displayed as/, with only theuploads/subdirectory visible. Any attempt to navigate higher than/fails instantly. - Check Shell Escape Vectors: Ensure interactive text editors provided in the user’s
bin/(such asnanoorvim) do not allow shell execution escapes. For instance, standardvimprovides:!/bin/shto break out of restricted shells; ensure advanced editors are replaced by constrained alternatives or configured with restricted flags.
Troubleshooting Common Chroot and Shell Incarceration Failures
| Error Message / Failure | Root Cause | Remediation Step |
|---|---|---|
fatal: bad ownership or modes for chroot directory |
One or more directories in the path leading to the chroot root are writable by non-root users. | Execute sudo chown root:root /jail/username and ensure permissions are 755 (never 777). |
Connection closed by remote host immediately after login |
ForceCommand internal-sftp configured for a standard SSH terminal session. |
If the user requires shell access rather than SFTP, do not specify internal-sftp; instead populate a minimal root filesystem (/dev, /bin, /lib) inside the jail. |
rbash: command not found for basic commands |
The command was omitted from the user’s isolated ~/bin directory. |
Create symbolic links from the approved system binary path into /home/username/bin/. |
By implementing rbash to constrain command execution and coupling it with OpenSSH ChrootDirectory jails, Ubuntu server administrators can effectively sandbox external contractors and automated ingestion pipelines, eliminating unauthorized lateral exploration across the host filesystem.