When you have obtained a webshell (can execute PHP code) but cannot execute system commands, this skill guides you to break through disable_functions and open_basedir restrictions.
In-depth reference
- Complete bypass code for methods A-G → references/disable-functions-bypass.md
- open_basedir bypass methods → references/open-basedir-bypass.md
- CTF PHP techniques (OPcache poisoning, polyglot files) → references/ctf-php-tricks.md
Phase 0: Information gathering (30-second assessment)
First confirm the scope of restrictions, as this determines the attack path:
<?php
echo "disable_functions: " . ini_get('disable_functions') . "\n";
echo "open_basedir: " . ini_get('open_basedir') . "\n";
echo "PHP version: " . phpversion() . "\n";
echo "OS: " . PHP_OS . "\n";
echo "Loaded extensions: " . implode(', ', get_loaded_extensions()) . "\n";
// 关键扩展检查
echo "FFI: " . (extension_loaded('ffi') ? 'YES' : 'NO') . "\n";
echo "imagick: " . (extension_loaded('imagick') ? 'YES' : 'NO') . "\n";
echo "iconv: " . (extension_loaded('iconv') ? 'YES' : 'NO') . "\n";
echo "putenv: " . (function_exists('putenv') ? 'YES' : 'NO') . "\n";
echo "mail: " . (function_exists('mail') ? 'YES' : 'NO') . "\n";
echo "error_log: " . (function_exists('error_log') ? 'YES' : 'NO') . "\n";
?>
Phase 1: disable_functions bypass decision tree
putenv() 可用?
├─ YES → mail()/error_log() 可用?
│ ├─ YES → 方法 A: LD_PRELOAD 劫持(最稳定,首选)
│ └─ NO → iconv 扩展加载?
│ ├─ YES → 方法 B: iconv + LD_PRELOAD
│ └─ NO → imagick 扩展?
│ ├─ YES → 方法 C: ImageMagick delegate
│ └─ NO → 下一分支
├─ NO → FFI 扩展 (PHP ≥ 7.4)?
│ ├─ YES → 方法 D: FFI 直接调用 system()
│ └─ NO → PHP < 7.4.21 / 8.0 < 8.0.8?
│ ├─ YES → 方法 E: PHP Backtrace UAF (CVE-2019-11043 等)
│ └─ NO → PCNTL 扩展?
│ ├─ YES → 方法 F: pcntl_exec()
│ └─ NO → 方法 G: ShellShock (CVE-2014-6271) / Apache mod_cgi
See the complete code for each method at references/disable-functions-bypass.md
Practical quick reference table
| What you see | Method | Command |
|---|---|---|
| putenv + mail available | LD_PRELOAD | Upload .so → putenv → mail() |
| putenv + error_log available | LD_PRELOAD | Same as above, use error_log() instead |
| putenv + iconv available | GCONV_PATH | Upload gconv-modules + .so |
| imagick already loaded | delegate injection | MVG/SVG payload |
| PHP ≥ 7.4 + FFI | FFI::cdef | Directly call system() |
| pcntl already loaded | pcntl_exec | fork + exec |
| Bash ≤ 4.3 | ShellShock | putenv environment variable injection |
| All fail | UAF exploit | Search for an exploit script matching the version |
Precautions
- Prioritize checking phpinfo() to confirm the environment; do not blindly try things
- The LD_PRELOAD method requires uploading a .so file; ensure there is a writable directory
- The FFI method is the most concise but requires a high PHP version
- In some Docker environments
/usr/sbin/sendmaildoes not exist → mail() does not trigger execve → switch to error_log - After successfully executing commands, remember to clean up the uploaded .so files