In this blog, we will be discussing the new functions we got to bypass PHP disable_functions and also the other tricks to do the same.
I (@TarunkantG) and one of my teammate (@__c3rb3ru5__ ) made
lazyFuzzer to fuzz the all PHP functions to check if they call
execve system call internally. In this blog mainly we will be discussing the difficulties we faced to make the Fuzzer and how we certainly solved those issues to get more new functions.
We also made a tool on the top of the findings this fuzzer did, here,
Announcing dfunc-bypasser for letting you know how strong your disable_function is and how you can bypass that. You can get the more details on the same while reading this blog.
Note: The functions we got are not in the default php installation, instead the php modules which get installed sometimes during normal installation.
So let’s dive into details:
There are 3 ways(known to us) to bypass disable_functions:
LD_PRELOAD: You use the PHP function which calls
execvesyscall internally, and using
LD_PRELOADyou overwrite the definition and get the shell. You can get the detailed writeup to do the same here. The known functions to do the same are
error_log. Or you can use
php-imagicklibrary to change the file type, which sometimes call
execveinternally, overwrite any definition from them to get the shell, for this you can get the detailed writeup here.
PHP-FPM: If the
PHP-FPMservice is running in the server, you can use that to get the shell, you can use Gopherus to generate the payload of
FastCGIthen urldecode it and write that payload to the sock file or the port of
fwrite. You can get the detailed writeup of the same here.
Or use any N-Day PHP exploit, which is not fixed in the given version in order to get the shell.
While playing the a lot of CTFs, I have seen that, these time a lot of CTF challenges needed to bypass the disable_functions whereas the well-known function for doing the same are only two(
error_log). So that gave me the idea to fuzz all the php functions and check if they call
First, I installed all the php-modules on the server and thought of fuzzing the functions from it’s minimum arguments to max arguments with the flag range of (-10,10), so for this we needed to know which functions takes how many arguments to run and if the argument type is string then which string should go, if it is file then which file and so on we need to figure out for all argument type. So now I have following task to complete:
First thing was to find out the, what number of argument the function needs? so I used the error messages of the functions which says,
exactly the number of argument should be used.
Note: For this I could have also used ReflectionFunction class to find out the max and the least numbers of arguments needed.
Now, we needed to check, what type of input the function takes? that also we solved using error ;). But the problem here is, you can’t get the types of arguments all in the once. You have to set the arguments such that the php can check the next argument.
Note: For this you can’t use
ReflectionFunction class because, this class mainly works for user defined functions not for php pre-defined(internal) functions.
As this will be too much of the task to do, I went to find a interesting string which can satisfy all types.
This was trivial task to do.
As the 1st step gave us the type of arguments to be send to the function. The types can be one of these:
NULL. So if you start fuzzing a function having argument type of int, string, file then your fuzzer will run for
3! times(As described earlier).
Now the task to find the string which satisfy almost all of these argument types. So I came with interesting string
This String can be used as
flag argument, we will be using integers from the range of (-10,10).
Object type argument, most of the time functions don’t take the input as Object.
Null is satisfied, because we fuzzed from min to max arguments.
Array we didn’t do because it’s not too common.
So now we have string which almost contains all of the types but not
There are two best answer for this:
- The main problem on fuzzing resource type argument was, How we will get to know that what and whose resource does the argument need? Let’s say one example,
socket_connect, this function need a resource argument, now how will you know that, which resource does this function need without checking the PHP manual of that ;).
Btw if anyone know how to find out using cli then please give me a ping.
- And the second answer is itself the name,
I got 4 new functions which can bypass PHP disable_functions using
LD_PRELOAD. All these functions are in different different modules of PHP.
mb_send_mail: If your system has
php-mbstringmodule installed then this function can be used to bypass php disable_functions.
imap_mail: If your system has
php-imapmodule installed then this function also can be used to bypass the php disable_functions.
libvirt_connect: If your system has
php-libvirt-phpmodule installed then this function also can be used to bypass disable_functions.
gnupg_init: If your system has
php-gnupgmodule installed then this function also can be used to bypass disable_functions.
You can get the file which has been used for this testing, here, lazyFuzzer.py.
This tool is to test how much strong your disable_functions is. The tool takes your input and tells you that, which function could possibly bypass the given disable_functions.
You can install this tool from here.