Unpatched PHP runtimes and misconfigured FastCGI Process Manager (PHP-FPM) pools remain primary targets for automated php2shell remote code execution (RCE) campaigns. Attackers routinely exploit exposed file upload endpoints, insecure deserialization, and CGI argument injection to drop persistent webshells inside public web directories. Hardening a production Linux web server requires strict configuration at three distinct layers: the php.ini runtime directives, the Nginx or Apache worker isolation boundaries, and filesystem permission locks.

1. Disable High-Risk Process Execution Functions in php.ini

The vast majority of PHP webshells rely on built-in system execution wrappers to spawn a reverse shell or run arbitrary bash commands under the www-data user. Unless your application explicitly invokes local CLI binaries, you should disable all OS-level execution functions in your active /etc/php/8.3/fpm/php.ini file:

; Disable dangerous OS command execution and process control functions
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_multi_exec,parse_ini_file,show_source,pcntl_exec,pcntl_fork

; Prevent PHP from fetching and executing remote scripts via include/require
allow_url_fopen = Off
allow_url_include = Off

; Hide PHP version headers from HTTP responses
expose_php = Off

; Restrict PHP filesystem access strictly to the application root
open_basedir = /var/www/html/:/tmp/

Setting open_basedir guarantees that even if a vulnerability exists within a third-party plugin, the PHP worker process cannot traverse upward into /etc/passwd or inspect sibling virtual hosts on the same machine.

2. Block PHP Execution Inside Upload and Cache Directories

File upload forms for avatars, attachments, or document imports are the number-one entry vector for webshells. Even when MIME-type checks are implemented in application code, attackers bypass weak filters using double extensions (such as avatar.jpg.php) or polyglot image headers. You must instruct Nginx to refuse script execution inside static storage directories:

# Nginx block: Deny PHP script execution in user upload folders
location ~* ^/(uploads|storage|cache|assets)/.*\.(php|php5|phtml|phar|inc)$ {
    deny all;
    return 403;
}

# Ensure FastCGI only processes existing local scripts
location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}

The try_files $uri =404; directive is critical: it prevents Nginx from passing non-existent image paths to the PHP interpreter when cgi.fix_pathinfo is mishandled.

3. PHP Security Directive Impact Comparison

Directive / Rule Configuration File Exploit Class Mitigated Production Overhead
disable_functions php.ini Webshell command execution (shell_exec, system) Zero
allow_url_include = Off php.ini Remote File Inclusion (RFI) payload injection Zero
open_basedir php.ini / Pool conf Directory traversal and cross-site file snooping Negligible (<1% I/O check)
try_files $uri =404 nginx.conf FastCGI path info spoofing on uploaded images Zero

4. Auditing Live Servers for Hidden Webshells via Linux CLI

If you suspect an older PHP installation was exposed prior to patching, run a targeted filesystem audit across your web root to locate obfuscated eval(base64_decode(...)) payloads or recently modified scripts:

# 1. Scan for obfuscated PHP webshell signatures
grep -rnE "(eval\s*\(|base64_decode\s*\(|gzinflate\s*\(|shell_exec\s*\(|passthru\s*\()" /var/www/html/

# 2. List all .php files modified in the last 72 hours
find /var/www/html/ -type f -name "*.php" -mtime -3 -ls

# 3. Verify no unexpected files exist inside the uploads directory
find /var/www/html/uploads/ -type f -name "*.php*"

After verifying the codebase is clean, restart PHP-FPM using sudo systemctl restart php8.3-fpm and enforce read-only file permissions (chmod 0440 or immutable deployment containers) on core application files so runtime workers cannot modify .php scripts on disk.