The security of a cloud server running a LAMP (Linux, Apache, MySQL, PHP) stack is of utmost importance, especially in today's landscape fraught with cyber threats. One way to fortify your server is through PHP function hardening, where potentially risky PHP functions are disabled to prevent exploitation.
We have identified the following PHP functions and have disabled those on Batoi Managed Hosting:
show_source
system
shell_exec
passthru
exec
phpinfo
popen
proc_open
allow_url_fopen
Let's explore why these functions can be vulnerable and explore alternative methods for implementing the same functionality.
1. show_source
What it does: Displays the source code of a PHP script with syntax highlighting.
Vulnerabilities: This function can leak sensitive information like database credentials, API keys, and application logic.
Alternatives: Use Code Repositories or Secure Internal Tools
Rather than exposing your code with show_source()
, you can use internal tools or code repositories for the same purpose.
// Old Way
// show_source("example.php");
// New Way
// Use code repositories like Git for sharing and viewing code
2. system
What it does: Executes an external command and outputs the result.
Vulnerabilities: Command injection risks if improperly sanitized.
Alternatives: Use PHP's built-in functions for the required functionality where possible, or thoroughly sanitize and validate all user inputs and variables used in system()
calls.
// Old Way
// system("ls " . $_GET['dir']);
// New Way
$files = scandir($_GET['dir']);
3. shell_exec
What it does: Executes commands via the shell.
Vulnerabilities: Similar to the system
, it poses a command injection risk.
Alternatives: Use PHP's built-in functions or restrict the scope of commands that can be executed.
// Old Way
// $output = shell_exec('ls');
// New Way
$files = scandir('.');
4. passthru
What it does: Executes an external command and displays raw output.
Vulnerabilities: Can be exploited for command injection.
Alternatives: Use built-in PHP functions or properly sanitize user inputs.
// Old Way
// passthru("cat " . $_GET['file']);
// New Way
$content = file_get_contents($_GET['file']);
5. exec
What it does: Executes an external program.
Vulnerabilities: Subject to command injection if not carefully implemented.
Alternatives: Use built-in PHP functions that perform the same operation or implement strict validation and sanitization measures.
// Old Way
// exec('rm ' . $file);
// New Way
unlink($file);
6. phpinfo
What it does: Outputs information about PHP's configuration.
Vulnerabilities: Leaks sensitive server configuration details, which could be a treasure trove for attackers.
Alternatives: Access this information internally and securely and ensure it is not accessible via web routes.
// Old Way
// phpinfo();
// New Way
// Access configuration information through internal and secure means
7. popen
What it does: Opens a pipe to a process executed via a command.
Vulnerabilities: Subject to command injection attacks.
Alternatives: Validate and sanitize input or use PHP built-in functions if feasible.
// Old Way
// $handle = popen('/bin/ls', 'r');
// New Way
$files = scandir('.');
8. proc_open
What it does: Executes a command and opens file pointers for input/output.
Vulnerabilities: Command injection risks similar to system and exec.
Alternatives: Consider combining PHP's socket functions and pcntl_fork
for Unix-like systems.
Below is a simplified example that attempts to mimic proc_open
functionality using pcntl_fork
and Unix sockets. This example will execute the ls
command:
$sockets = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM,
STREAM_IPPROTO_IP);
if ($sockets === false || count($sockets) < 2) {
die("Unable to create socket pair.");
}
$pid = pcntl_fork();
if ($pid === -1) {
die("Could not fork process");
} elseif ($pid === 0) { // child
fclose($sockets[0]);
// Redirect the output to the socket
fclose(STDOUT);
fclose(STDERR);
$stdout = fopen('php://fd/' . (int)$sockets[1], 'w');
$stderr = fopen('php://fd/' . (int)$sockets[1], 'w');
exec('ls'); // Example command; replace with your own command
fclose($stdout);
fclose($stderr);
exit(0);
} else { // parent
fclose($sockets[1]);
$output = stream_get_contents($sockets[0]);
// Read from the socket to get command output
// Wait for child process to exit
pcntl_waitpid($pid, $status);
echo "Command output:\n" . $output;
fclose($sockets[0]);
}
9. allow_url_fopen
What it does: Enables the URL-aware fopen
wrappers.
Vulnerabilities: This can allow attackers to execute remote files, leading to remote code execution (RCE) vulnerabilities.
Alternatives: Use the cURL
library or PHP’s http
wrapper for more secure remote file
operations.
// Old Way
// $content = file_get_contents('http://example.com');
// New Way
$ch = curl_init('http://example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$content = curl_exec($ch);
curl_close($ch);
Conclusion
Security is an ongoing concern, and it's crucial to remain vigilant. By disabling these PHP functions, we can significantly reduce the risk surface of our cloud server. While PHP function hardening is just one layer of defense, it's a robust one that complements other security measures in creating a more secure server environment.