In the last edition of HackRon, in our talk “The Red Team always wins” we tackled some techniques used during penetration tests including how to bypass disable_functions and open_basedir, among others. A common situation whenever a penetration test is run consists on finding the application of certain hardening measures in web servers. This complicates privilege elevation or even its own use in order to pivot towards other points of the corporate network.
To begin with, we could highlight disabling the usage of dangerous functions used in order to run operating system commands or start processes, among other traditional measures applied. Functions such as system() or shell_exec() are usually found disabled through the PHP directives defined in the configuration file php.ini. Perhaps, some other less known functions such as dl() (enabling dynamically loading a PHP extension) can go unnoticed by the systems administrator, therefore they are not disabled. That is the reason why during a penetration test, it is very common enumerating which functions are found enabled just in case one has been forgotten.
On the other hand, a usual measure consists on restricting the access to the file system from the PHP scripts that are run in the server. This is done, restricting the directory tree where you can operate using the open_basedir directive. For example, if file access is restricted in the /var/www/ tree, a PHP script could not read the /etc/passwd file despite the user holds the appropriate permissions. This way, if the PHP code is run through the vulnerabilities in the web environment (arbitrary file uploads, local file inclusions, etc.), the range of actions that could be carried out is restricted and more complicated.
In these very restricted scenarios where it is practically only possible to create and read files, the pentester usually tends to locate configuration files or hardcoded passwords in the code making therefore lateral movement possible (for example, reusing a password in the SSH). Nevertheless when not even this is effective, we have to bypass disable_functions and open_basedir.
One of the easiest techniques to implement as well as one of less widespread is the abuse of the mail() and putenv() functionality. This technique is not new, since it was already reported to PHP in the year 2008 by gat3way, however it is still currently working. Therefore, it is possible to modify environment variables using the putenv() function allocating any desired value on the LD_PRELOAD variable. In broad terms, LD_PRELOAD provides the possibility of pre-load a library .so before the rest of the libraries. In such a way that if a programme uses any library function (for example, libc.so) our library will be executed first instead of the one that it was supposed to be executed. This way, we can hook functions modifying their behaviour as we please.
The problem is that even though we can create a favourable environment allocating LD_PRELOAD as a value to one of our ad-hoc created libraries, it is still necessary to run some programme. Actually, this was our original problem. However, there is a solution: in UNIX environments the mail() function runs a binary. Then, if PHP documentation is analysed, the following fragment can be observed:
The mail() implementation in Windows differs too much from the implementation in Unix. First, it doesn’t use a local binary in order to compose messages since it only operates in direct sockets, meaning that it is necessary a MTA listening in a network socket (which could be either in the localhost either in a remote machine).
This is confirmed by analysing what happens whenever a PHP calling the mail() function is run::
<?php mail("a", "a", "a", "a"); ?>
Then, our library will be pre-loaded whenever the binary called when using mail() is run, in such a way that we are enabled to make any behavioural modifications if we hook one of the functions being called.
Chankro: disable_functions and open_basedir bypass tool
Tarlogic Red Team has created a small utility to automatically bypass disable_functions and open_basedir during penetration tests.
Using Chankro, a PHP is generated. This PHP will act as a dropper creating a library .so in the server and the binary (for example, a meterpreter) or script bash (for example, a reverse shell) that can be freely run. Later on, putenv() and mail() will be called in order to launch the process.
The executing file, the PHP name, the server architecture (64 or 32) and the absolute path from where the files will be dropped should be transferred as arguments. Please find in the following example, a PHP generated providing the possibility of obtaining a reverse shell using Netcat:
Once the generated file is uploaded to the server we have access to using any vulnerability in the web environment, our “rev.sh” can be run sending a request with curl:
This tool could be found in Tarlogic GitHub