Home • Blog • Article

Difference Between SFTP And Shell Users: A Practical Guide

By Fathima Nourin TM • •

Understanding the Difference Between SFTP and Shell Users

Server access control forms the foundational layer of any robust WordPress hosting infrastructure. Whether executing routine maintenance, triaging core database lockups, or deploying code updates, system administrators must choose between two primary remote access methods: Secure File Transfer Protocol (SFTP) and interactive Shell (Secure Shell or SSH) access. While both protocols utilize the underlying SSH transport layer to encrypt data in transit, they grant vastly different operating system privileges, execution vectors, and security postures.

Improperly configured user permissions represent a primary entry vector for privilege escalation attacks across LEMP and LAMP stacks. Granting an interactive shell account when a restricted file-transfer mechanism suffices exposes the entire server ecosystem to arbitrary command execution, privilege escalation via misconfigured binaries, and lateral movement. Conversely, over-restricting developers can lead to insecure shadow administrative practices, such as storing cleartext credentials in shared document repositories or disabling permission checks on the web server user. This technical guide explores the architectural, operational, and security distinctions between SFTP and Shell users, providing concrete system hardening procedures.

Core Architecture and Request Lifecycle

To understand the security boundaries of SFTP and Shell users, one must examine their respective execution lifecycles within a Linux server environment. Both services initiate connections over TCP port 22 (or a custom port) managed by the OpenSSH daemon (sshd). Authentication occurs uniformly via public-private key pairs or challenge-response passwords. However, the divergence occurs immediately post-authentication.

🚨 Facing an active site error or malware warning?

Chat with an engineer on WhatsApp within 15 minutes.

💬 Chat on WhatsApp

When an SFTP user authenticates, the sshd daemon intercepts the request and invokes the internal subsystem binary (typically internal-sftp) or an external binary (such as /usr/lib/openssh/sftp-server). This subsystem does not allocate a pseudo-terminal (pty) and does not execute an interactive command interpreter (such as Bash, Zsh, or Dash). Instead, it runs a restricted loop processing binary file-transfer requests (e.g., SSH_FXP_OPEN, SSH_FXP_READ, SSH_FXP_MKDIR). Furthermore, system administrators configure SFTP-only accounts with a ChrootDirectory directive. This chroot jail restricts the user’s root view to a specific directory (e.g., /var/www/html), preventing them from traversing upward to system configuration files like /etc/passwd or /etc/shadow.

Conversely, a Shell user authenticates and receives an interactive shell session complete with a pseudo-terminal allocation. The user executes arbitrary binaries, scripts, and system commands subject only to standard Linux discretionary access control (DAC) permissions (User/Group/Other read, write, execute bits) and optional Access Control Lists (ACLs) or SELinux/AppArmor policies. A shell user can spawn background processes, compile source code, establish outbound network connections via curl or nc, and modify system-wide configurations if granted sudo privileges. This level of access transforms a compromised account into a potential beachhead for complete root-level server compromise.

Root Cause Analysis: Vulnerability Vectors and Impact

The operational risks associated with Shell users stem from the breadth of execution capabilities they introduce. Consider a multi-tenant WordPress hosting environment where an agency developer requires access to upload custom themes and plugins. If that developer receives a Shell account instead of a scoped SFTP account, several security boundaries are immediately weakened:

  • Arbitrary File Execution: A shell user can upload an uncompiled binary or a custom script written in Python, Perl, or PHP and execute it directly via the command line, bypassing the web application firewall (WAF) or web server execution context.
  • Privilege Escalation via SUID Binaries: If the local Linux kernel or installed system packages contain unpatched local privilege escalation (LPE) vulnerabilities (e.g., CVE-2021-4034 PolicyKit local privilege escalation), an interactive shell provides the exact execution vector required to leverage those exploits.
  • Credential Harvesting: Shell users can inspect environment variables (printenv), read configuration files containing database passwords (wp-config.php), or search historical command buffers (.bash_history) for leaked secrets.
  • Lateral Movement: Interactive access allows users to probe internal network interfaces (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) using tools like nmap or simple bash sockets, potentially pivoting to internal databases, Redis caches, or administrative management planes.

By contrast, an SFTP-only user configured with proper chroot restrictions is physically incapable of executing arbitrary binaries or probing internal network boundaries, significantly reducing the blast radius of a compromised set of credentials.

Step-by-Step Implementation and Remediation Guide

System administrators must strictly separate user roles. Below is the precise procedure for provisioning a secure, chrooted SFTP-only user alongside a properly restricted shell user on an Ubuntu/Debian-based WordPress server.

Step 1: Create a Dedicated SFTP Group

Create a dedicated system group for all SFTP-restricted file management users. Run the following command via root:

sudo groupadd sftp_users

Step 2: Configure the SSH Daemon for Chroot Enforcement

Modify the OpenSSH server configuration file to automatically apply a chroot jail whenever a member of the sftp_users group logs in. Open /sshd_config using an editor:

sudo nano /etc/ssh/sshd_config

Scroll to the bottom of the file and append the following conditional block. Ensure this block is placed at the very end of the configuration file to prevent overriding global parameters:

Match Group sftp_users
    ChrootDirectory /var/www/vhosts/%u
    ForceCommand internal-sftp
    X11Forwarding no
    AllowTcpForwarding no
    PermitTunnel no
    AllowAgentForwarding no

Save the file and test the SSH configuration for syntax errors before restarting the daemon:

sudo sshd -t
sudo systemctl restart ssh

Step 3: Create the SFTP User and Directory Structure

The directory specified in ChrootDirectory (and its parent directories up to the root) must be owned by root and must not be writable by any other user or group. This is a strict OpenSSH security requirement.

# Create the parent web root structure if it does not exist
sudo mkdir -p /var/www/vhosts/client_site

# Set root ownership on the chroot base directory
sudo chown root:root /var/www/vhosts/client_site
sudo chmod 755 /var/www/vhosts/client_site

# Create the user, assigning them to the sftp_users group and setting their shell to /bin/false
sudo useradd -g sftp_users -d / -s /bin/false client_user

# Set a secure password for the user
sudo passwd client_user

# Create a writable directory within the chroot jail for actual file uploads
sudo mkdir -p /var/www/vhosts/client_site/public_html
sudo chown client_user:sftp_users /var/www/vhosts/client_site/public_html
sudo chmod 755 /var/www/vhosts/client_site/public_html

Step 4: Provisioning a Controlled Shell User (When Required)

When a system administrator or senior developer genuinely requires shell access (e.g., to run WP-CLI commands, composer updates, or git deployments), provision a standard user with restricted shell access, rather than giving them unrestricted root privileges or arbitrary script execution vectors.

# Create a standard user with a valid shell (or rbash for restricted bash)
sudo useradd -m -s /bin/bash dev_admin
sudo passwd dev_admin

# Add the user to the www-data group to ensure proper file permission parity for WordPress
sudo usermod -aG www-data dev_admin

To restrict a shell user further without resorting to full SFTP chroot, configure Restricted Bash (rbash). This limits the user to running commands only within their defined PATH, preventing them from navigating outside their home directory or executing unauthorized binaries.

# Change the user's shell to restricted bash
sudo chsh -s /bin/rbash dev_admin

# Create a locked-down bin directory for allowed commands
sudo mkdir -p /home/dev_admin/bin
sudo chown root:root /home/dev_admin/bin
sudo chmod 755 /home/dev_admin/bin

# Symlink only approved administrative utilities (e.g., wp-cli, git)
sudo ln -s /usr/local/bin/wp /home/dev_admin/bin/wp
sudo ln -s /usr/bin/git /home/dev_admin/bin/git

# Enforce a restricted PATH in the user's profile
echo 'export PATH=$HOME/bin' | sudo tee /home/dev_admin/.bash_profile
sudo chown dev_admin:dev_admin /home/dev_admin/.bash_profile
sudo chmod 644 /home/dev_admin/.bash_profile

Production Hardening and Edge Cases

Deploying SFTP chroot jails and restricted shells in high-traffic production environments introduces specific technical caveats, caching conflicts, and performance trade-offs that administrators must manage.

File Ownership and Permission Conflicts in WordPress:
When an SFTP user uploads a plugin or core update, those files take on the ownership of the SFTP user account (e.g., client_user:sftp_users). However, the PHP-FPM worker pool typically executes WordPress execution threads under the web server user (e.g., www-data or nginx). If file permissions are set incorrectly (e.g., 600 or 700), PHP-FPM will throw 500 Internal Server Error responses because it lacks read/execute permissions. Ensure that newly created files within the web root adhere to safe default permission masks (umask 022) or enforce automatic permission correction via deployment scripts.

SSH Key Authentication Enforcement:
Passwords remain a primary vector for brute-force attacks against SSH and SFTP services. Production servers must disable password authentication entirely for both SFTP and Shell users, enforcing strict public-key cryptography.

# Edit /etc/ssh/sshd_config to enforce keys
PasswordAuthentication no
PubkeyAuthentication no # (Ensure PubkeyAuthentication is explicitly set to yes globally)
ChallengeResponseAuthentication no
PermitRootLogin no

SFTP and WP-CLI Automation Trade-offs:
Developers frequently attempt to run WP-CLI commands over SFTP. This is architecturally impossible because SFTP does not parse shell commands. Automated deployment pipelines must instead use SSH key-based authentication combined with forced command execution in the authorized_keys file to securely run deployment scripts without granting full interactive shell access.

# Example authorized_keys restriction for automated deployments
command="/usr/local/bin/wp cache flush --path=/var/www/html",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... deploy_bot@company

Diagnostic Verification and Checklist

Following implementation, administrators must systematically verify access controls to ensure that chroot jails hold and that shell restrictions function as intended. Execute the diagnostic verification checks outlined below.

Verification Test Command / Action Expected Result
SFTP Chroot Escape Test sftp client_user@server_ip then cd ../../../ User cannot traverse above their designated chroot base directory.
SFTP Shell Execution Test ssh client_user@server_ip Connection is immediately closed with message: This service allows sftp connections only. or similar refusal.
Restricted Shell Path Test ssh dev_admin@server_ip then run /bin/sh Command fails or returns restricted environment error due to rbash enforcement.
SSH Daemon Syntax Check sudo sshd -t Returns zero exit status with no syntax errors reported.
Log Monitoring sudo tail -f /var/log/auth.log Verify successful public key handshakes and reject password attempts instantly.

Continuous monitoring of authentication logs (/var/log/auth.log or /var/log/secure) via centralized log management tools ensures rapid detection of anomalous login spikes, brute-force sweeps, or unauthorized permission escalation attempts. Implementing these strict boundaries between file transfer protocols and command-line interfaces preserves structural integrity across mission-critical WordPress architectures.

Follow SiteSuraksha on Google
Add us to your preferred sources for verified WordPress & hosting guides.
FREE 30-SECOND DIAGNOSTIC

Is Your Website Fast & Secure?

Run an instant scan for security vulnerabilities, bloated plugins, and TTFB latency.

🔍 Test Your Site Now →
Map Your Issue to Guaranteed IT Care
Security & Malware
Hacks, 0-day exploits & backup failures
Pro Care (₹5,420/mo) →
Speed & Cloud Bills
Slow checkout, high TTFB & cloud waste
Pro Care (₹5,420/mo) →
ERP & Automation
GST pipelines, RPA & AI support agents
Enterprise (₹14,999/mo) →
EXPERT WORDPRESS CARE

Need Help Securing or Speeding Up Your Site?

Get 24/7 proactive security WAF, daily cloud backups, and sub-second speed optimization from ₹3,470/mo.

💬 Chat on WhatsApp Explore Plans
← Back to All Articles