PHP - Useful Functions & disable_functions/open_basedir bypass
PHP Command & Code Execution
PHP Command Execution
exec - Returns last line of commands output
passthru - Passes commands output directly to the browser
system - Passes commands output directly to the browser and returns last line
shell_exec - Returns commands output
`` (backticks) - Same as shell_exec()
popen - Opens read or write pipe to process of a command
proc_open - Similar to popen() but greater degree of control
preg_replace
pcntl_exec - Executes a program (by default in modern and not so modern PHP you need to load the pcntl.so
module to use this function)
mail / mb_send_mail - **This function is used to send mails, but it can also be abused to inject arbitrary commands inside the $options
parameter. This is because php mail
function usually call sendmail
binary inside the system and it allows you to put extra options**. However, you won't be able to see the output of the executed command, so it's recommended to create shell script that writes the output to a file, execute it using mail, and print the output:
dl - This function can be used to dynamically load a PHP extension. This function won't be present always, so you should check if it's available before trying to exploit it. Read this page to learn how to exploit this function.
PHP Code Execution
Apart from eval there are other ways to execute PHP code: include/require can be used for remote code execution in the form of Local File Include and Remote File Include vulnerabilities. ${<php code>} - If your input gets reflected in any PHP string, it will be executed. eval() assert() - identical to eval() preg_replace('/.*/e',...) - /e does an eval() on the match create_function() - Create a function and use eval() include() include_once() require() require_once() $_GET['func_name']($_GET['argument']); $func = new ReflectionFunction($_GET['func_name']); $func->invoke(); or $func->invokeArgs(array()); serialize/unserialize
disable_functions & open_basedir
Disabled functions is the setting that can be configured in .ini
files in PHP that will forbid the use of the indicated functions. Open basedir is the setting that indicates to PHP the folder that it can access.
The PHP setting sue to be configured in the path /etc/php7/conf.d or similar.
Both configuration can be seen in the output of phpinfo()
:
open_basedir Bypass
open_basedir
will configure the folders that PHP can access, you won't be able to to write/read/execute any file outside those folders, but also you won't even be able to list other directories.
However, if somehow you are able to execute arbitrary PHP code you can try the following chunk of codes to try to bypass the restriction.
Listing dirs with glob:// bypass
In this first example the glob://
protocol with some path bypass is used:
Note1: In the path you can also use /e??/*
to list /etc/*
and any other folder.
Note2: It looks like part of the code is duplicated, but that's actually necessary!
Note3: This example is only useful to list folders not to read files
Full open_basedir bypass abusing FastCGI
If you want to learn more about PHP-FPM and FastCGI you can read the first section of this page.
If php-fpm
is configured you can abuse it to completely bypass open_basedir:
Note that the first thing you need to do is find where is the unix socket of php-fpm. It use to be under /var/run
so you can use the previous code to list the directory and find it.
Code from here.
This scripts will communicate with unix socket of php-fpm (usually located in /var/run if fpm is used) to execute arbitrary code. The open_basedir
settings will be overwritten by the PHP_VALUE attribute that is sent.
Note how eval
is used to execute the PHP code you send inside the cmd parameter.
Also note the commented line 324, you can uncomment it and the payload will automatically connect to the given URL and execute the PHP code contained there.
Just access http://vulnerable.com:1337/l.php?cmd=echo file_get_contents('/etc/passwd');
to get the content of the /etc/passwd
file.
You may be thinking that just in the same way we have overwritten open_basedir
configuration we can overwrite disable_functions
. Well, try it, but it won't work, apparently disable_functions
can only be configured in a .ini
php configuration file and the changes you perform using PHP_VALUE won't be effective on this specific setting.
disable_functions Bypass
If you manage have PHP code executing inside a machine you probably want to go to the next level and execute arbitrary system commands. In this situation is usual to discover that most or all the PHP functions that allow to execute system commands have been disabled in disable_functions
.
So, lets see how you can bypass this restriction (if you can)
Automatic bypass discovery
You can use the tool https://github.com/teambi0s/dfunc-bypasser and it will indicate you which technique you can use to bypass disable_functions
.
Bypassing using other system functions
Just return to the begging of this page and check if any of the command executing functions isn't disabled and available in the environment. If you find just 1 of them, you will be able to use it to execute arbitrary system commands.
LD_PRELOAD bypass
It's well known that some functions in PHP like mail()
are going to execute binaries inside the system. Therefore, you can abuse them using the environment variable LD_PRELOAD
to make them load an arbitrary library that can execute anything.
Functions that can be used to bypass disable_functions with LD_PRELOAD
mail
mb_send_mail
: If your system hasphp-mbstring
module installed then this function can be used to bypass php disable_functions.imap_mail
: If your system hasphp-imap
module installed then this function also can be used to bypass the php disable_functions.libvirt_connect
: If your system hasphp-libvirt-php
module installed then this function also can be used to bypass disable_functions.gnupg_init
: If your system hasphp-gnupg
module installed then this function also can be used to bypass disable_functions.new imagick()
: You can find here a writeup to learn how to abuse this class
You can find here the fuzzing script that was used to find those functions.
Here is a library you can compile to abuse the LD_PRELOAD
env variable:
Bypass using Chankro
In order to abuse this misconfiguration you can Chankro. This is a tool that will generate a PHP exploit that you need to upload to the vulnerable server and execute it (access it via web).
Chankro will write inside the victims disc the library and the reverse shell you want to execute and will use theLD_PRELOAD
trick + PHP mail()
function to execute the reverse shell.
Note that in order to use Chankro, mail
and putenv
cannot appear inside the disable_functions
list.
In the following example you can see how to create a chankro exploit for arch 64, that will execute whoami
and save the out in /tmp/chankro_shell.out, chankro will write the library and the payload in /tmp and the final exploit is going to be called bicho.php (that's the file you need to upload to the victims server):
If you find that mail function is blocked by disabled functions, you may still be able to use the function mb_send_mail. More information about this technique and Chankro here: https://www.tarlogic.com/en/blog/how-to-bypass-disable_functions-and-open_basedir/
"Bypass" using PHP capabilities
Note that using PHP you can read and write files, create directories and change permissions. You can even dump databases. Maybe using PHP to enumerate the box you can find a way to escalate privileges/execute commands (for example reading some private ssh key).
I have created a webshell that makes very easy to perform this actions (note that most webshells will offer you this options also): https://github.com/carlospolop/phpwebshelllimited
Modules/Version dependent bypasses
There are several ways to bypass disable_functions if some specific module is being used or exploit some specific PHP version:
dl function
****PHP 7.0=7.4 (*nix)****
****Imagick 3.3.0 PHP >= 5.4****
****PHP 5.2.4 ionCube****
****PHP <= 5.2.9 Windows****
****PHP 5.2.4/5.2.5 cURL****
****PHP Perl Extension Safe_mode****
****PHP 5.2.3 -Win32std****
****PHP 5.2 FOpen exploit****
****Bypass via mem****
****mod_cgi****
****PHP 4 >= 4.2.-, PHP 5 pcntl_exec****
ALL IN ONE
The code with more options mentioned here available I have found is https://github.com/l3m0n/Bypass_Disable_functions_Shell/blob/master/shell.php
Other Interesting PHP functions
List of functions which accept callbacks
These functions accept a string parameter which could be used to call a function of the attacker's choice. Depending on the function the attacker may or may not have the ability to pass a parameter. In that case an Information Disclosure function like phpinfo() could be used. Function => Position of callback arguments 'ob_start' => 0, 'array_diff_uassoc' => -1, 'array_diff_ukey' => -1, 'array_filter' => 1, 'array_intersect_uassoc' => -1, 'array_intersect_ukey' => -1, 'array_map' => 0, 'array_reduce' => 1, 'array_udiff_assoc' => -1, 'array_udiff_uassoc' => array(-1, -2), 'array_udiff' => -1, 'array_uintersect_assoc' => -1, 'array_uintersect_uassoc' => array(-1, -2), 'array_uintersect' => -1, 'array_walk_recursive' => 1, 'array_walk' => 1, 'assert_options' => 1, 'uasort' => 1, 'uksort' => 1, 'usort' => 1, 'preg_replace_callback' => 1, 'spl_autoload_register' => 0, 'iterator_apply' => 1, 'call_user_func' => 0, 'call_user_func_array' => 0, 'register_shutdown_function' => 0, 'register_tick_function' => 0, 'set_error_handler' => 0, 'set_exception_handler' => 0, 'session_set_save_handler' => array(0, 1, 2, 3, 4, 5), 'sqlite_create_aggregate' => array(2, 3), 'sqlite_create_function' => 2,
Information Disclosure
Most of these function calls are not sinks. But rather it maybe a vulnerability if any of the data returned is viewable to an attacker. If an attacker can see phpinfo() it is definitely a vulnerability. phpinfo posix_mkfifo posix_getlogin posix_ttyname getenv get_current_user proc_get_status get_cfg_var disk_free_space disk_total_space diskfreespace getcwd getlastmo getmygid getmyinode getmypid getmyuid
Other
extract - Opens the door for register_globals attacks (see study in scarlet). parse_str - works like extract if only one argument is given. putenv ini_set mail - has CRLF injection in the 3rd parameter, opens the door for spam. header - on old systems CRLF injection could be used for xss or other purposes, now it is still a problem if they do a header("location: ..."); and they do not die();. The script keeps executing after a call to header(), and will still print output normally. This is nasty if you are trying to protect an administrative area. proc_nice proc_terminate proc_close pfsockopen fsockopen apache_child_terminate posix_kill posix_mkfifo posix_setpgid posix_setsid posix_setuid
Filesystem Functions
According to RATS all filesystem functions in php are nasty. Some of these don't seem very useful to the attacker. Others are more useful than you might think. For instance if allow_url_fopen=On then a url can be used as a file path, so a call to copy($_GET['s'], $_GET['d']); can be used to upload a PHP script anywhere on the system. Also if a site is vulnerable to a request send via GET everyone of those file system functions can be abused to channel and attack to another host through your server.
Open filesystem handler
fopen tmpfile bzopen gzopen SplFileObject->__construct
Write to filesystem (partially in combination with reading)
chgrp chmod chown copy file_put_contents lchgrp lchown link mkdir move_uploaded_file rename rmdir symlink tempnam touch unlink imagepng - 2nd parameter is a path. imagewbmp - 2nd parameter is a path. image2wbmp - 2nd parameter is a path. imagejpeg - 2nd parameter is a path. imagexbm - 2nd parameter is a path. imagegif - 2nd parameter is a path. imagegd - 2nd parameter is a path. imagegd2 - 2nd parameter is a path. iptcembed ftp_get ftp_nb_get scandir
Read from filesystem
file_exists -- file_get_contents file fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype glob is_dir is_executable is_file is_link is_readable is_uploaded_file is_writable is_writeable linkinfo lstat parse_ini_file pathinfo readfile readlink realpath stat gzfile readgzfile getimagesize imagecreatefromgif imagecreatefromjpeg imagecreatefrompng imagecreatefromwbmp imagecreatefromxbm imagecreatefromxpm ftp_put ftp_nb_put exif_read_data read_exif_data exif_thumbnail exif_imagetype hash_file hash_hmac_file hash_update_file md5_file sha1_file -- highlight_file -- show_source php_strip_whitespace get_meta_tags
Last updated